🪡

【必見】これから学ぶべきTypeScriptフレームワーク 4選

2022/09/30に公開約12,300字4件のコメント

はじめに

今回の記事では、私の独断と偏見でこれから学ぶべきTypeScriptフレームワークを4つ徹底解説する。今回の記事を参考に、TypeScriptを深く学ぶことにつながれば幸いである。TypeScriptが使われているフレームワークは数多く存在するので、何から手を付ければいいのかわからない人も少なくないだろう。もしこの記事を読んでいるプログラマーがTypeScriptのフレームワークを選んでいるのに悩んでいたら、今回の記事は参考になるはずだ

あくまで個人の一見解に過ぎないが、参考になれば幸いである。

これから学ぶべきTypeScriptフレームワーク

  • Next.js
  • Nuxt3
  • NestJS
  • SolidJS

それぞれ順番に解説する。

1.Next.js

Next.jsはReactベースで開発されたTypeScriptフレームワークである。最大の特徴は、URLルーティングと呼ばれるリクエストされたURLに対して呼び出すアクションを決定する仕組みや、Web開発を効率よくするための機能がデフォルトで含まれていることである。

Reactをベースに開発されたNext.jsはよくReactと比較される。両者の最大の違いは次の2つ。

  • サーバ機能の有無:Next.jsにはサーバ機能がある一方で、Reactにはサーバ機能がない。(ReactはあくまでUIを設計するためのライブラリ)
  • URLルーティングの設定:Next.jsは自動でルーティングを生成できる。初期化する時に生成されたフォルダにファイルを配置することでURLが生成される。

Nextjsの特徴は以下の通り。

  • 画像・レンダリングの最適化:画像のサイズに応じて、オリジナル画像をトリミングしてから配信してくれる
  • ルーティングの自動化:Next.jsではpagesフォルダの中にファイルを配置するだけで勝手にルーティングが生成される。例えば、pages/myaccount.tsxファイルを作成すると、https://localhost/myaccountというURLでアクセスできるようになる。
  • コマンド一つで雛形を生成できる手軽さ:Next.jsはコマンド入力だけで開発したいプロジェクトに必要なパッケージ・ライブラリのインストールや簡易的な設定を済ませられる。コマンド一つで開発に必要な雛形を生成できるので効率的に開発を進められる環境が整っている。
  • 学習コストの低さ:Next.jsはReactをベースに設計・開発されているので、Reactの知識があれば簡単に習得できる。

ただし、Next.jsはもとはJavaScriptで開発されているので、TypeScriptに対応するためには別途設定が必要である。

インストール方法

以下のコマンドを入力する。公式がテンプレートを用意しているのでGitHubからインストールする形で使う。

# project-nameには自分のプロダクトの名前を入れる。この場合はnpmを使う。
npx create-next-app <project-name> --use-npm --example "https://github.com/vercel/next-learn/tree/master/basics/basics-final"

ルートディレクトリと同じ場所にtsconfig.jsonを作成する。次に、以下のコマンドを入力するとtsconfig.jsonが自動で変換される。

npm run dev
yarn dev

コマンド入力後、tsconfig.jsonが以下のようになる。

tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true
  },
  "exclude": ["node_modules"],
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
}

次に、以下のコマンドでTypeScriptをインストールする。

# npm経由
npm install --save-dev typescript @types/react @types/node

# yarn経由
yarn add --dev typescript @types/react @types/node

以下のコマンドを入力すれば開発者サーバが立ち上がる。

npm start

サーバを起動すれば、Next.jsは以下のファイルを作成する。

  • tsconfig.json:上述の通り。
  • next-env.d.ts:これはNext.jsの型がTypeScriptコンパイラに認識されるようにするファイル。決して編集してはいけない

最後にファイルの拡張子を変える。デフォルトの拡張子に応じて変更する。主にcomponentlibpagesディレクトリの中のファイルの拡張子を変更する。(ほとんどは.tsxに変更する)

詳細な拡張子の変更は以下のGitHubリポジトリのREADMEを確認。

https://github.com/shota-nukumizu/mui-nextjs-starter

環境構築はこれで終了。

サンプルコード

components/layout.tsx
import Head from 'next/head'
import Image from 'next/image'
import styles from './layout.module.css'
import utilStyles from '../styles/utils.module.css'
import Link from 'next/link'

const name = '[Your Name]'
export const siteTitle = 'Next.js Sample Website'

export default function Layout({
  children,
  home
}: {
  children: React.ReactNode
  home?: boolean
}) {
  return (
    <div className={styles.container}>
      <Head>
        <link rel="icon" href="/favicon.ico" />
        <meta
          name="description"
          content="Learn how to build a personal website using Next.js"
        />
        <meta
          property="og:image"
          content={`https://og-image.vercel.app/${encodeURI(
            siteTitle
          )}.png?theme=light&md=0&fontSize=75px&images=https%3A%2F%2Fassets.zeit.co%2Fimage%2Fupload%2Ffront%2Fassets%2Fdesign%2Fnextjs-black-logo.svg`}
        />
        <meta name="og:title" content={siteTitle} />
        <meta name="twitter:card" content="summary_large_image" />
      </Head>
      <header className={styles.header}>
        {home ? (
          <>
            <Image
              priority
              src="/images/profile.jpg"
              className={utilStyles.borderCircle}
              height={144}
              width={144}
              alt={name}
            />
            <h1 className={utilStyles.heading2Xl}>{name}</h1>
          </>
        ) : (
          <>
            <Link href="/">
              <a>
                <Image
                  priority
                  src="/images/profile.jpg"
                  className={utilStyles.borderCircle}
                  height={108}
                  width={108}
                  alt={name}
                />
              </a>
            </Link>
            <h2 className={utilStyles.headingLg}>
              <Link href="/">
                <a className={utilStyles.colorInherit}>{name}</a>
              </Link>
            </h2>
          </>
        )}
      </header>
      <main>{children}</main>
      {!home && (
        <div className={styles.backToHome}>
          <Link href="/">
            <a>← Back to home</a>
          </Link>
        </div>
      )}
    </div>
  )
}

▼引用はこちら

https://github.com/shota-nukumizu/mui-nextjs-starter

2.Nuxt3

Nuxt3はVueベースのフロントエンドフレームワークである。(読み方は「ナクスト」)主な特徴は以下の通り。

  • アプリケーション開発に必要な機能がデフォルトで揃っている
  • 開発時の起動&ホットリロードが高速
  • デフォルトでTypeScriptが使える(Next.jsにはない強みがある)
  • VSCodeの拡張機能VolarでVueの型検知ができる
  • Tailwindのモジュールがデフォルトで用意されている
  • Vueの知識があればスムーズに習得できる
  • コマンド一つで開発に必要な機能がデフォルトで揃っている
  • サーバ機能がついているので、APIを開発できる(Next.jsも同様にできる)

しかし、2022年10月1日現時点でNuxt3は開発途上なので、情報量が少なくエコシステムが未発達である。それゆえ、学習コストは低くない。

インストール方法

小難しい設定がなく、このコマンドを入力してしまえばセットアップは終了。

# project-nameにはプロジェクトの名前を入れる
npx nuxi init <project-name>
cd <project-name>
npm i # 依存関係のインストール
npm run dev -- -o # こちらのコマンドで開発者サーバが立ち上がる

サンプルコード

VueではHTML、CSSやTypeScript(JavaScript)を分割して書く。

src/index.vue
<template>
  <article>
    <h2>Todo</h2>

    <form @submit.prevent="handleAdd">
      <input type="text" v-model="newTodo" placeholder="Add a Todo" />
    </form>

    <template v-if="data && data.length">
      <ol class="todo-list">
        <li v-for="item in filterItems" :key="item.id">
          <p>{{ item.body }}</p>
          <button type="button" @click="handleDelete(item)">Delete</button>
        </li>
      </ol>
      <PrevNext :totalPage="totalPage" @change="onPageChange" />
    </template>
  </article>
</template>

<script setup lang="ts">
const { data } = await useFetch("/api/todos/list");
watch(data.value, async (newData, prev) => {
  await $fetch("/api/todos/save", {
    method: "POST",
    body: JSON.stringify(newData),
  });
});

const { totalPage, filterItems, onPageChange } = usePagination(data.value);
</script>

<script lang="ts">
export default {
  name: "IndexPage",
  data() {
    return {
      newTodo: "",
    };
  },
  methods: {
    async handleAdd() {
      if (!this.newTodo) return;
      let id = 0;

      if (this.data.length) {
        id = this.data.reduce((acc, cur) => {
          return Math.max(acc, cur.id);
        }, id);
      }

      const todo = {
        id: id + 1,
        body: this.newTodo,
        updatedAt: new Date(),
      };
      this.newTodo = "";
      this.data.unshift(todo);
      return;
    },

    async handleDelete(todo) {
      this.data.splice(this.data.indexOf(todo), 1);
    },
  },
};
</script>

<style scoped>
.todo-list {
  list-style: none;
  padding: 0;
  margin: 1rem;
}

.todo-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
</style>

▼引用はこちら

https://codesandbox.io/s/xohmi

3.NestJS

NestJSは簡単に言えば、Express同様にNode.jsのフレームワークである。主な特徴は以下の通り。

  • デフォルトでTypeScriptが使える
  • Expressの知識をそのまま応用できる
  • OOP(オブジェクト指向プログラミング)、FP(関数型プログラミング)、FRP(関数型リアクティブプログラミング)の要素をフル活用できる
  • テストが簡単。専用のテストフレームワークが用意されている
  • 設計思想がAngularに影響されている
  • GraphQLとREST APIの開発を両方ともサポートしている
  • マイクロサービスを開発しやすい
  • WebSocketと連携できる
  • 拡張性が高い
  • コマンド一つで開発に必要な機能がデフォルトで揃っている

日本語に対応していないものの、公式ドキュメントが非常にわかりやすく丁寧に書かれており初心者でもスムーズに習得できるのが最大の魅力である。

インストール方法

Nuxt3と同様に小難しい設定は不要で、こちらのコマンドさえ入力してしまえばインストールが終わる。

npm i -g @nestjs/cli
nest new <project-name>

サンプルコード

プログラムが短いので2つのファイルを紹介する。

main.ts
import { NestFactory } from '@nestjs/core'
import { AppModule } from './app.module'

// この処理で開発者サーバを起動できる。
async function bootstrap() {
  const app = await NestFactory.create(AppModule)
  await app.listen(3000)
}

bootstrap()
app.module.ts
import { Module } from '@nestjs/common'
import { AppController } from './app.controller'
import { AppService } from './app.service'

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

▼引用はこちら

https://docs.nest-book.jp/ttebunestjs/no

4.SolidJS

SolidJSはReactベースで開発されたJavaScriptフレームワークである。主な特徴は以下の通り。

  • Next.jsと同様にReactの知識さえあれば簡単に習得できる
  • Viteに対応しており、高速でプロダクトを開発できる
  • 非常に軽量
  • 日本語ドキュメントが充実していて、学習コストが低い
  • フロントエンド・バックエンド両対応
  • ブラウザでコードを動かせるPlaygroundの環境が整っている
  • コマンド一つで開発に必要な機能がデフォルトで揃っている。TypeScriptにも対応

SolidJSは開発コストの低さと面白さ、ユニークさを両立している画期的なフレームワークである。

インストール方法

これも小難しい設定は不要で、このコマンドを入力すればインストールと開発者サーバの起動が完了する。環境構築の易しさはNestJSに匹敵する

npx degit solidjs/templates/ts my-app
cd my-app
npm i # 依存関係のインストール
npm run dev # 開発者サーバの立ち上げ

サンプルコード

こちらは公式が用意しているSolidJSで開発されたTodoアプリのサンプルである。

main.tsx
import { createSignal, batch, For } from "solid-js";
import { render } from "solid-js/web";
import { createLocalStore, removeIndex } from "./utils";

type TodoItem = { title: string; done: boolean };

const App = () => {
  const [newTitle, setTitle] = createSignal("");
  const [todos, setTodos] = createLocalStore<TodoItem[]>("todos", []);

  const addTodo = (e: SubmitEvent) => {
    e.preventDefault();
    batch(() => {
      setTodos(todos.length, {
        title: newTitle(),
        done: false,
      });
      setTitle("");
    });
  };

  return (
    <>
      <h3>Simple Todos Example</h3>
      <form onSubmit={addTodo}>
        <input
          placeholder="enter todo and click +"
          required
          value={newTitle()}
          onInput={(e) => setTitle(e.currentTarget.value)}
        />
        <button>+</button>
      </form>
      <For each={todos}>
        {(todo, i) => (
          <div>
            <input
              type="checkbox"
              checked={todo.done}
              onChange={(e) => setTodos(i(), "done", e.currentTarget.checked)}
            />
            <input
              type="text"
              value={todo.title}
              onChange={(e) => setTodos(i(), "title", e.currentTarget.value)}
            />
            <button onClick={() => setTodos((t) => removeIndex(t, i()))}>
              x
            </button>
          </div>
        )}
      </For>
    </>
  );
};

render(App, document.getElementById("app")!);
utils.tsx
import { createEffect } from "solid-js";
import { createStore, SetStoreFunction, Store } from "solid-js/store";

export function createLocalStore<T extends object>(
  name: string,
  init: T
): [Store<T>, SetStoreFunction<T>] {
  const localState = localStorage.getItem(name);
  const [state, setState] = createStore<T>(
    localState ? JSON.parse(localState) : init
  );
  createEffect(() => localStorage.setItem(name, JSON.stringify(state)));
  return [state, setState];
}

export function removeIndex<T>(array: readonly T[], index: number): T[] {
  return [...array.slice(0, index), ...array.slice(index + 1)];
}

:::

▼引用はこちら

https://www.solidjs.com/examples/todos

おわりに

今回の記事では、個人の独断と偏見でこれから学ぶべきTypeScriptフレームワークを4つ紹介した。

  • Next.js
  • Nuxt3
  • NestJS
  • SolidJS

今回の記事で紹介したすべてのTypeScriptフレームワークに共通することは、コマンド入力一つで開発に必要な機能がデフォルトで揃っていることである。そのためWeb開発を効率よく進めやすい。

この記事をきっかけに、読者がTypeScriptでのWeb開発に興味を持つことにつながれば幸いである。

参考サイト

GitHubで編集を提案

Discussion

以下の記述ですが、

SolidJSはReactベースで開発されたJavaScriptフレームワークである。

これ以前に書いてある以下などと同様な意味で記載しているなら、誤りだと思います。

Next.jsはReactベースで開発された

sterashima78 さんに同意するとともに補足しますと、そもそも SolidJS がこの並びにあることがおかしいと思います。SolidJS はどちらかというと React や Vue などの「ライブラリ」と同じレイヤーに属するもののはずで、「フレームワーク」として紹介するのは無理があるはずだからです(もし SolidJS をベースとした「フレームワーク」を勧めたいのであれば、SolidStart などが妥当かと思います)。

また、他の箇所にも初心者の誤解を招きかねない記述が散見されるように思われます。たとえば、Next.js のセットアップ方法として

npx create-next-app <project-name> --use-npm --example "https://github.com/vercel/next-learn/tree/master/basics/basics-final"

を実行すると書かれていますが、これは公式のチュートリアル用のプロジェクトをセットアップするためのコマンドであり、常にこうするわけではありません(もちろん、Vercel は Examples などの参考実装を多数用意してくれていますので、学習用にそれに類するサンプルとして紹介することは構わないと思いますが、そうしたことに言及せず一般化して書くことはおかしいと思います)。最もベーシックなセットアップ方法は Next.js のドキュメントの一番最初

npx create-next-app@latest --typescript
# or
yarn create next-app --typescript
# or
pnpm create next-app --typescript

と書かれていますので、これを記述すべきかと思います(さらに述べると、「コマンド一つ」でという長所が本文中に何度も現れていますが、こちらのコマンドを紹介していないために js のプロジェクトを ts に対応させる手順説明が続いてしまっており、その結果コマンド一つでセットアップが終わっておらず、本文内でも矛盾が生じているように感じました)。

上は一例であり、他にも本文中に誤りや曖昧な点があるようなため、一度内容を見直されたほうがいいのではないかと思いました。

また、その他として、ここでリストアップしなかったフレームワークについても、「なぜそれを選ばなかったのか」に関して述べたほうが良いのではないかと思いました。たとえばフロントエンドのフレームワークに限っても、Remix や Astro、SvelteKit など、2022 年現在は他にも有力なものが多くあるわけで、それらが存在していないかのように一切触れないのはやはり初学者に対してミスリーディングであるように感じますし、フレームワークを比較検討したいと思った読者にとっては学びがないように思います。

  • インストール方法にnpm以外の方法を書くと別途でnpmやyarn、pnpmの違いを説明しなければならなくなること

横から失礼します。
勝手な想像ですが、指摘されているのはyarnやpnpmのインストール方法が記述されていないことではなく、--typescriptをつければ最初からtsのプロジェクトを始められるのに、わざわざjsで始めてtsに変換する方法を記載してるからではないでしょうか?

npx create-next-app@latest --typescript

せめてこれを記載してあれば、「コマンド入力だけで」を主張できるのでは?
あたかもNext.jsではtsを扱うのに一手間かかるような印象を与えている気がします。

RemixとRedwoodはどうでしょうか?

ログインするとコメントできます