触ったことのない 7 つのフロントエンドのフレームワークで Hello, world! してみる

# はじめに

名前は知っているけどまだ触ったことのないフレームワークで Hello, world! していきます。
※ この記事では Hello, world! のみ行うため、特徴などを深掘りすることはありません。ご了承ください。

# Gatsby

[Gatsby](https://www.gatsbyjs.com/) は React ベースの SSG （ Static Site Generator ）です。また、 DSG （ Deferred Static Generation ）にも対応しています。
特徴として独自の [GraphQL data layer](https://www.gatsbyjs.com/docs/tutorial/part-4/#meet-gatsbys-graphql-data-layer) を持ち、サイトを構築するためのデータをすべて保持します（データを data layer に取り込むためには Gatsby が提供するプラグインを使用します）。この GraphQL data layer からデータを取得するには各コンポーネント内で GraphQL クエリを記述します。

## Hello, world! - Gatsby

[Quick Start](https://www.gatsbyjs.com/docs/quick-start/) を参考に環境構築を行います。
※ Node.js は v18.0.0 以上をご使用ください。

```bash
$ npm init gatsby

What would you like to call your site?
✔ · My Gatsby Site
What would you like to name the folder where your site will be created?
✔ gatsby/ my-gatsby-site
✔ Will you be using JavaScript or TypeScript?
· TypeScript
✔ Will you be using a CMS?
· No (or I'll add it later)
✔ Would you like to install a styling system?
· No (or I'll add it later)
✔ Would you like to install additional features with other plugins?No items were selected
```

生成されたフォルダは以下のようになります。
※ `node_modules` 、 `.git` は割愛します。

```bash
my-gatsby-site
├── src
│   ├── images
│   │   └── icon.png
│   └── pages
│       ├── 404.tsx
│       └── index.tsx
├── .gitignore
├── gatsby-config.ts
├── package.json
├── README.md
├── tsconfig.json
└── yarn.lock
```

`$ yarn develop` で以下の URL にアクセスできるようになります。

- `http://localhost:8000/` ... `src/pages/index.tsx` 内の UI を表示
- `http://localhost:8000/___graphql` ... GraphQL API をテストするための UI を表示

`src/pages/index.tsx` を以下のように書き換え、 Hello, world! します。

```src/pages/index.tsx
import * as React from "react";
import type { HeadFC, PageProps } from "gatsby";

const IndexPage: React.FC<PageProps> = () => {
  return (
    <h1>Hello, world!</h1>
  );
};

export default IndexPage;

export const Head: HeadFC = () => <title>Hello, world!</title>;
```

# Remix

[Remix](https://remix.run/) は React ベースのフルスタック Web フレームワークです。
特徴は [Server/Client Model](https://remix.run/docs/en/v1/pages/philosophy#serverclient-model) を採用していることです。 SSG のように静的ファイルをビルドするのではなく、ネットワークに送るデータ量を減らすことで高速化を図っています。

## Hello, world! - Remix

[Jokes App Tutorial](https://remix.run/docs/en/v1/tutorials/jokes) を参考に環境構築を行います。
※ Nodejs は v14.17.0 または v16.0.0 以上、 npm は v7 以上をご使用ください。

```bash
$ npx create-remix@latest

? Where would you like to create your app? ./my-remix-app
? What type of app do you want to create? Just the basics
? Where do you want to deploy? Choose Remix App Server if you're unsure; it's
easy to change deployment targets. Remix App Server
? TypeScript or JavaScript? TypeScript
? Do you want me to run `npm install`? Yes
```

生成されたフォルダは以下のようになります。
※ `node_modules` は割愛します。

```bash
blog-tutorial
├── app
│   ├── routes
│   │   └── index.tsx
│   ├── entry.client.tsx
│   ├── entry.server.tsx
│   └── root.tsx
├── public
│   └── favicon.ico
├── .eslintrc.js
├── .gitignore
├── package-lock.json
├── package.json
├── README.md
├── remix.config.js
├── remix.env.d.ts
└── tsconfig.json
```

`app/routes/index.tsx` を以下のように書き換え、 Hello, world! します。

```app/routes/index.tsx
export default function Index() {
  return <h1>Hello, world!</h1>;
}
```

# Svelte

[Svelte](https://svelte.jp/) はコンポーネントフレームワークです。（厳密には、宣言的なコンポーネントを、効率的な Vanilla JS に変換するコンパイラです。）
特徴として [Write less code](https://svelte.jp/blog/write-less-code) / [No virtual DOM](https://svelte.jp/blog/virtual-dom-is-pure-overhead) / [Truly reactive](https://svelte.jp/blog/svelte-3-rethinking-reactivity) の3つがあります。

- Write less code ... 重要なのは読みやすさという思想のもと、ボイラープレート（ `useMemo` や `useEffect` にあたる動作）に終焉を告げる
- No virtual DOM ... 仮想 DOM を使用しないで宣言的で状態駆動型の UI 開発を行う
- Truly reactive ... JavaScript そのものに、リアクティビティ（値の変更を検知して DOM へ反映する処理）をもたらす

## Hello, world! - Svelte

[GETTING STARTED](https://svelte.jp/docs#getting-started) を参考に環境構築を行います。
※ 公式ドキュメントに沿って [SvelteKit](https://kit.svelte.jp/) を使用します。

```bash
$ npm create svelte@latest myapp

Welcome to SvelteKit!

✔ Which Svelte app template? › Skeleton project
✔ Add type checking with TypeScript? › Yes, using TypeScript syntax
✔ Add ESLint for code linting? … No / Yes
✔ Add Prettier for code formatting? … No / Yes
✔ Add Playwright for browser testing? … No / Yes
✔ Add Vitest for unit testing? … No / Yes

Your project is ready!
✔ Typescript
  Inside Svelte components, use <script lang="ts">
```

生成されたフォルダは以下のようになります。（ `$ npm install` 後に `.svelte-kit` フォルダと `package-lock.json` が作成されます。）
※ `node_modules` は割愛します。

```
myapp
├── .svelte-kit
│   ├── generated
│   │   ├── client-manifest.js
│   │   ├── client-matchers.js
│   │   ├── nodes
│   │   │   ├── 0.js
│   │   │   ├── 1.js
│   │   │   └── 2.js
│   │   └── root.svelte
│   ├── types
│   │   ├── route_meta_data.json
│   │   └── src
│   │       └── routes
│   │           └── $types.d.ts
│   ├── ambient.d.ts
│   └── tsconfig.json
├── src
│   ├── routes
│   │   └── +page.svelte
│   ├── app.d.ts
│   └── app.html
├── static
│   └── favicon.png
├── .gitignore
├── .npmrc
├── package-lock.json
├── package.json
├── README.md
├── svelte.config.js
├── tsconfig.json
└── vite.config.js
```

`src/routes/+page.svelte` を以下のように書き換え、 Hello, world! します。

```src/routes/+page.svelte
<h1>Hello, world!</h1>
```

# SolidJS

[SolidJS](https://www.solidjs.com/) は UI を作成するための JavaScript ライブラリです。（フレームワークではありませんが触っていきます。ご了承ください。）
特徴は、 Svelte 同様仮想 DOM を使用せず、 React ライクに記述できるところです。また、 Vanilla JS とほぼ遜色の無いパフォーマンスを誇っています。

## Hello, world! - SolidJS

[Solid を試す](https://www.solidjs.com/guides/getting-started#solid-%E3%82%92%E8%A9%A6%E3%81%99) を参考に環境構築を行います。

```
$ npx degit solidjs/templates/ts my-app
```

生成されたフォルダは以下のようになります。（ `$ npm install` 後に `package-lock.json` が作成されます。）
※ `node_modules` は割愛します。

```
my-app
├── src
│   ├── assets
│   │   └── favicon.ico
│   ├── App.module.css
│   ├── App.tsx
│   ├── index.css
│   ├── index.tsx
│   └── logo.svg
├── .gitignore
├── index.html
├── package-lock.json
├── package.json
├── pnpm-lock.yaml
├── README.md
├── tsconfig.json
└── vite.config.ts
```

`src/App.tsx` を以下のように書き換え、 Hello, world! します。

```src/App.tsx
import type { Component } from "solid-js";

const App: Component = () => {
  return <h1>Hello, world!</h1>;
};

export default App;
```

# Fresh

[Fresh](https://fresh.deno.dev/) は Deno 製の Web フレームワークです。
特徴として、事前のビルドステップを行わず、エッジでの Just-in-time レンダリングを実現しています。また、 [Islands Architecture](https://jasonformat.com/islands-architecture/) を取り入れており、デフォルトではクライアントに JavaScript は送られません。

## Hello, world! - Fresh

[Getting Started](https://fresh.deno.dev/#getting-started) を参考に環境構築を行います。
※ Deno CLI は v1.25.0 以降をご使用ください。

```
$ deno run -A -r https://fresh.deno.dev my-project

Fresh has built in support for styling using Tailwind CSS. Do you want to use this? [y/N] N
Do you use VS Code? [y/N] y
```

生成されたフォルダは以下のようになります。

```
my-project
├── .vscode
│   ├── extensions.json
│   └── settings.json
├── components
│   └── Button.tsx
├── islands
│   └── Counter.tsx
├── routes
│   ├── api
│   │   └── joke.ts
│   ├── [name].tsx
│   └── index.tsx
├── static
│   ├── favicon.ico
│   └── logo.svg
├── deno.json
├── deno.lock
├── dev.ts
├── fresh.gen.ts
├── import_map.json
├── main.ts
└── README.md
```

`routes/index.tsx` を以下のように書き換え、 Hello, world! します。

```routes/index.tsx
import { Head } from "$fresh/runtime.ts";

export default function Home() {
  return (
    <>
      <Head>
        <title>Hello, world!</title>
      </Head>
      <h1>Hello, world!</h1>
    </>
  );
}
```

# RedwoodJS

[RedwoodJS](https://redwoodjs.com/) はフルスタック Web フレームワークです。
特徴は、スタートアップ企業向けのフレームワークであり、 React や GraphQL 、 Prisma を使用して開発行います。また、多くの機能を提供しており、 [features](https://github.com/redwoodjs/redwood#features) にまとめられていますが、この他にも認証（ Auth0 など）や CSS フレームワーク（ Tailwind CSS など）の設定も、コマンドラインから呼び出すだけで可能になります。

## Hello, world! - RedwoodJS

[Quick Start](https://redwoodjs.com/docs/quick-start) を参考に環境構築を行います。
※ Nodejs は v14.19.x 以上 16.x 以下、 Yarn は v1.15 以上をご使用ください。

```bash
$ yarn create redwood-app my-redwood-project

------------------------------------------------------------------
🌲⚡️ Welcome to RedwoodJS! ⚡️🌲
------------------------------------------------------------------
✔ Compatibility checks passed
✔ Language preference
  › TypeScript
✔ Git preference
  › Initialize a git repo
✔ Creating Redwood app
  ✔ Creating directory '/.../my-redwood-project'
✔ Installing packages
  ✔ Running 'yarn install'... (This could take a while)
✔ Generating types
✔ Initializing a git repo
```

生成されたフォルダは以下のようになります。
※ `node_modules` 、 `.git` は割愛します。

```bash
my-redwood-project
├── .redwood
│   └── types
│   │   ├── includes
│   │   │   ├── all-currentUser.d.ts
│   │   │   ├── api-globImports.d.ts
│   │   │   ├── api-globalContext.d.ts
│   │   │   ├── api-scenarios.d.ts
│   │   │   ├── api-test-globals.d.ts
│   │   │   ├── web-routerRoutes.d.ts
│   │   │   ├── web-routesPages.d.ts
│   │   │   └── web-test-globals.d.ts
│   │   └── mirror
│   │       ├── api
│   │       │   └── src
│   │       │       └── directives
│   │       │           ├── requireAuth
│   │       │           │   └── index.d.ts
│   │       │           └── skipAuth
│   │       │               └── index.d.ts
│   │       └── web
│   │           └── src
│   │               └── pages
│   │                   ├── FatalErrorPage
│   │                   │   └── index.d.ts
│   │                   └── NotFoundPage
│   │                       └── index.d.ts
│   ├── schema.graphql
│   └── telemetry.txt
├── .vscode
│   ├── extensions.json
│   ├── launch.json
│   └── settings.json
├── .yarn
│   ├── releases
│   │   └── yarn-3.3.0.cjs
│   └── install-state.gz
├── api
│   ├── db
│   │   └── schema.prisma
│   ├── src
│   │   ├── directives
│   │   │   ├── requireAuth
│   │   │   │   ├── requireAuth.test.ts
│   │   │   │   └── requireAuth.ts
│   │   │   └── skipAuth
│   │   │       ├── skipAuth.test.ts
│   │   │       └── skipAuth.ts
│   │   ├── functions
│   │   │   └── graphql.ts
│   │   ├── graphql
│   │   │   └── .keep
│   │   ├── lib
│   │   │   ├── auth.ts
│   │   │   ├── db.ts
│   │   │   └── logger.ts
│   │   └── services
│   │       └── .keep
│   ├── types
│   │   └── graphql.d.ts
│   ├── jest.config.js
│   ├── package.json
│   ├── server.config.js
│   └── tsconfig.json
├── scripts
│   ├── .keep
│   ├── seed.ts
│   └── tsconfig.json
├── web
│   ├── public
│   │   ├── README.md
│   │   ├── favicon.png
│   │   └── robots.txt
│   ├── src
│   │   ├── components
│   │   │   └── .keep
│   │   ├── layouts
│   │   │   └── .keep
│   │   └── pages
│   │   │   ├── FatalErrorPage
│   │   │   │   └── FatalErrorPage.tsx
│   │   │   └── NotFoundPage
│   │   │       └── NotFoundPage.tsx
│   │   ├── App.tsx
│   │   ├── index.css
│   │   ├── index.html
│   │   └── Routes.tsx
│   ├── jest.config.js
│   ├── package.json
│   └── tsconfig.json
├── .editorconfig
├── .env
├── .env.defaults
├── .env.example
├── .gitignore
├── .nvmrc
├── .yarnrc.yml
├── graphql.config.js
├── jest.config.js
├── package.json
├── prettier.config.js
├── README.md
├── redwood.toml
└── yarn.lock
```

プロジェクト作成後、 `$ yarn redwood generate page hello-world /` コマンドを入力し、 Hello, world! を表示するための画面を作成します。作成後は `web/src/pages` フォルダ内に `HelloWorldPage` フォルダが以下の構成で作成されます。

```bash
HelloWorldPage
├── HelloWorldPage.stories.tsx
├── HelloWorldPage.test.tsx
└── HelloWorldPage.tsx
```

作成した `HelloWorldPage.tsx` を以下のように書き換え、 Hello, world! します。

```web/src/pages/HelloWorldPage/HelloWorldPage.tsx
import { MetaTags } from '@redwoodjs/web'

const HelloWorldPage = () => {
  return (
    <>
      <MetaTags title="Hello, world!" description="Hello, world! page" />
      <h1>Hello, world!</h1>
    </>
  )
}

export default HelloWorldPage
```

# Astro

[Astro](https://astro.build/) はコンテンツにフォーカスした高速な Web サイトを構築するためのオールインワン Web フレームワークです。
特徴として、特定のUIに依存せず、 React 、 Preact 、 Svelte 、 Vue 、 SolidJS 、 Lit などをサポートします。また [Astro Islands](https://docs.astro.build/ja/concepts/islands/) という [Islands Architecture](https://jasonformat.com/islands-architecture/) が元となったアーキテクチャを採用しています。

## Hello, world! - Astro

[Quick Start](https://redwoodjs.com/docs/quick-start) を参考に環境構築を行います。
※ Nodejs は v.14.18.0 または v16.12.0 以上をご使用ください。

```
$ npm create astro@latest

✔ Where would you like to create your new project? … tutorial
✔ How would you like to setup your new project? › a few best practices 
✔ Template copied!
✔ Would you like to install npm dependencies? (recommended) … yes
✔ Packages installed!
✔ Would you like to initialize a new git repository? (optional) … yes
✔ Git repository created!
✔ How would you like to setup TypeScript? › Strict
✔ TypeScript settings applied!
```

生成されたフォルダは以下のようになります。
※ `node_modules` 、 `.git` は割愛します。

```
tutorial
├── .vscode
│   ├── extensions.json
│   └── launch.json
├── public
│   └── favicon.svg
├── src
│   ├── components
│   │   └── Card.astro
│   ├── layouts
│   │   └── Layout.astro
│   └── pages
│   │   └── index.astro
│   └── env.d.ts
├── .gitignore
├── astro.config.mjs
├── package-lock.json
├── package.json
├── README.md
└── tsconfig.json
```

`src/pages/index.astro` を以下のように書き換え、 Hello, world! します。

```src/pages/index.astro
---
import Layout from "../layouts/Layout.astro";
---

<Layout title="Hello, world!">
  <h1>Hello, world!</h1>
</Layout>
```

# おわりに

今回 7 つのフレームワークを触ってみましたが、かなりのものが React ベースで書けるため、取っ付き易かったです。また、これらフレームワークの思想や特徴は面白いものばかりでした。そのため、技術的に挑戦できるプロジェクトでは、これらのフレームワークを使用してみる価値は大いにあると思います。
また Next.js v13 や Nuxt v3 に関してもまだキャッチアップの途中なので、このあたりも引き続き学んでいきたいと思います。