Gatsby.jsとNext.jsとNuxt.jsを比較する
ReactフレームワークのGatsby.jsとNext.js、VueフレームワークのNuxt.js、これらの主要なJSフレームワークで静的サイトを構築して得た気づきをご紹介します。
【結論】どれか1つ選ぶならGatsby.js
Nuxt.js、Next.js、Gatsby.jsの順番で使いました。技術レベルのブレもあるため、完全にフラットな視点で選ぶのが難しいのが本音ですが、どれか1つ選ぶならGatsby.jsにします。その後、Next.js、Nuxt.jsと続きます。
詳細は以下に続きます。
開発環境の違い
Next.jsがベストです。Zero Config(ゼロコンフィグ)を謳っていて、文字通り「設定が不要」です。もちろん、拡張することもできます。
私が行った拡張はたった1つ。イメージのドメイン設定だけです。
// next.config.js
module.exports = {
images: {
domains: [process.env.DOMAIN, "0.gravatar.com", "secure.gravatar.com"],
},
};
※この設定はコンポーネント側で直接指定もできるので、その場合は本当にゼロコンフィグになります。
Gatsby.jsは、npm init gatsby
実行時の質問に答えるだけで、ほとんどの設定が終わるためストレスフリーです。また、スターターテーマが豊富なので、それを使って設定の問題を回避することもできます。
Nuxt.jsは、コンポーネントの自動インポート機能が登場したり、以前よりも格段に扱いやすくはなりましたが、まだまだ細かい設定が必要で、ヨーイドン!での開発スピードはNext.jsに劣ります。
開発サーバーの立ち上がりや、ホットリロード(自動更新)に関してもNext.jsが速いです。
TypeScriptとの相性
Gatsby.jsとNext.jsは設定不要で使えます。Nuxt.jsは要設定です。
ReactとVueの違いにも言えることですが、Nuxt.jsとTypeScriptはとにかく相性が悪いです。導入に手間がかかる上、Vuexは別設定が必要だったり、JSXで開発した後は特にストレスフルです。
TypeScriptでの開発を考えるなら、Gatsby.jsかNext.jsです。
覚えやすさ
Next.jsがベストです。getStaticProps(データ操作)とgetStaticPaths(パス操作)の2つだけ覚えればいいので、非常にシンプルです。動的ページの生成で真価を発揮します。
Gatsby.jsは動的ページの生成ルールが特殊で、覚えやすさはNext.jsに劣ります。ただ、一旦ルールを覚えさえすれば、Next.jsよりも使いやすいと個人的には感じています。
Nuxt.jsはライフサイクルが非常に面倒です。開発時のサーバー側の操作はfetchやasyncDataで、クライアント側の操作はmoutedで、静的ファイル生成時はpayloadを使って…と、独自のルールがいくつもあり、細かいことができるのは確かなのですが、その分覚えることが多く疲れます。静的サイトの構築においてはメリットを実感する機会は少ないです。
覚えることが多いと、ブランクが発生した場合に変化をキャッチアップする時間も余計にかかるため、シンプルに扱えることに越したことはありません。
開発のしやすさ
Next.jsと悩むところですが、useStaticQueryが使えるGatsby.jsに軍配を上げます。
データの扱いと言えば、コンポーネント間で受け渡しするか、ReduxやVuexのようにストアで管理するのが一般的ですが、useStaticQueryはコンポーネント単体でデータを扱えるようにする技術です。
例えば、Headless CMSからサイトタイトルとディスクリプションのデータを取得し、ヘッダーコンポーネントで表示するとします。
この場合、ストアで管理するには不適切(不釣り合い)なデータと言えるので、ページ単位やレイアウト単位でデータを取得して、ヘッダーコンポネートに渡す必要があります。
例として、Next.jsでのコードです。
// components/SiteHeader.tsx
export const SiteHeader = (props: {
siteTitle: string;
description: string;
}) => {
const { siteTitle, description } = props;
return (
<>
<div>{siteTitle}</div>
<div>{description}</div>
</>
);
};
// pages/sample.tsx
import { SiteHeader } from "../components/SiteHeader";
export const Sample = (props: {
generalSettings: { siteTitle: string; description: string };
}) => {
const {
generalSettings: { siteTitle, description },
} = props;
return (
<>
<SiteHeader siteTitle={siteTitle} description={description} />
<div>Body</div>
<div>Footer</div>
</>
);
};
export const getStaticProps = async () => {
const generalSettings = await getGeneralSettings();
return {
props: { generalSettings },
};
};
export default Sample;
一方、Gatsby.jsでuseStaticQueryを使うと、引数が不要になるため、そのコンポーネント単体でデータの取得から表示まで完結します。以下がサンプルコードです。
// useStaticQuery使用
export const SiteHeader = () => {
const {
site: { siteTitle, description },
} = useStaticQuery<HeaderQuery>(
graphql`
query Header {
site: sanitySiteSettings {
siteTitle
description
}
}
`
);
return (
<>
<div>{siteTitle}</div>
<div>{description}</div>
</>
);
};
同じようなことができるライブラリもあると思いますが、これをデフォルトで使えるという理由だけでGatsby.jsを選ぶくらい便利な機能です。
汎用性
フレームワークだけでなく言語にも通じる話ですが、技術やツールを選ぶ上で「汎用性」の観点は重要です。つまり、どちらを身につけた方が、より仕事に活かせるかです。
これに関しては、ReactとVueの話でもあるので、両者を含めたテーマにはなりますが、世界的にも、日本国内だけ見ても、Reactの方が仕事(求人)は多いため、Gatsby.jsかNext.jsの扱いに慣れていた方が汎用性は高いと言えます。
また、WordPressのブロックエディターがReactを採用しているのも大きなポイントだと思っていて、WordPress系のスキルがメインの場合は、React系フレームワークを強く推します。
ただ、需要と供給のバランスはいつどうなるか分からないので、余裕があればVue(Nuxt.js)にも慣れておくのがベストです。(正直、慣れれば両者の違いはさほど気になりません)