【Next.js和訳】Migrating to Next.js/Migrating from CRA
この記事について
この記事は、Migrating to Next.js/Migrating from Create React Appの記事を和訳したものです。
記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。
Migrating from Create React App
このガイドでは、イジェクトされていない既存の Create React App プロジェクトから Next.js に移行する方法を理解することができます。Next.js に移行することで、以下のことが可能になります。
- ページごとに、どのdata fetching戦略を選択する。
- インクリメンタル・スタティック・リジェネレーションを使用して、トラフィックが入ってくるとバックグラウンドで再レンダリングを行い、既存のページを更新する。
- API Routesを使用します。
他にもいろいろあります。それでは、移行を完了するための一連の手順を説明します。
package.json
のアップデートと dependencies
Next.js に移行するための最初のステップは、package.json
と依存関係を更新することです。以下の作業を行います。
-
react-scripts
を削除します(ただし、react
とreact-dom
は残します)。React Router を使用している場合は、react-router-dom
も削除します。 -
next
をインストールします。 - Next.js 関連のコマンドを
scripts
に追加します。一つはnext dev
で、これはlocalhost:3000
で開発サーバーを動かすものです。また、プロダクションビルドを作成・開始するために、next build
とnext start
も追加しましょう。
以下は、package.json
の例です。
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"next": "latest",
"react": "latest",
"react-dom": "latest"
}
}
静的アセットとコンパイル済み出力
Create React App ではentry HTML fileにpublic
ディレクトリを使用していますが、Next.js ではスタティックアセットにpublic
ディレクトリを使用しています。ここに静的資産を追加することも可能ですが、Create React App では JavaScript ファイルから直接インポートすることをお勧めします。
- 画像やフォント、その他の静的アセットを
public
に移動します。 - アプリケーションのエントリーポイントである
index.html
を Next.js に変換します。<head>
のコードは、カスタムdocument.js
に移動します。すべてのページで共有されるレイアウトは、カスタム_app.js
に移動します。 - CSS/Sass ファイルについては、Stylingを参照してください。
-
.gitignore
に.next
を追加します。
Creating Routes & Linking
Create React App では、React Router を使うことが多いと思います。サードパーティのライブラリを使う代わりに、Next.js は独自のfile-system based routingを搭載しています。
- すべての
Route
コンポーネントを、pages
ディレクトリ内の新しいファイルに変換します。 - 動的なコンテンツを必要とするルート(例:
/blog/:slug
)については、Next.js でDynamic Routesを使用することができます(例:pages/blog/[slug].js
)。slug
の値はクエリパラメータでアクセスできます。たとえば、ルート/blog/first-post
は、クエリオブジェクト{ 'slug': 'first-post' }
をpages/blog/[slug].js
に転送します(詳しくはこちら)。
詳しくは React Router からの移行 をご覧ください。
Styling
Next.js には、CSS、Sass、CSS-in-JSのサポートが組み込まれています。
Create React App を使えば、React コンポーネント内で.css
ファイルを直接インポートすることができます。Next.js でも同じことができますが、これらのファイルはCSS Modulesである必要があります。グローバルなスタイルについては、グローバルスタイルシートを追加するために、カスタム _app.js
が必要になります。
Web API への安全なアクセス
クライアントサイドでレンダリングするアプリケーション(Create React App など)では、window
、localStorage
、navigator
などの Web API にすぐにアクセスすることができます。
Next.js はプリレンダリングを使用しているため、クライアントサイドにいるときだけ、これらの Web API に安全にアクセスする必要があります。例えば、以下のコードスニペットは、クライアントサイドでのみ window
へのアクセスを許可します。
if (typeof window !== "undefined") {
// これで `window` にアクセスできるようになりました。
}
Web API に安全にアクセスするための推奨方法は、クライアントサイドでのみ実行されるuseEffect
hook を使用することです。
import { useEffect } from "react"
useEffect(() => {
// これで `window` にアクセスできるようになりました。
}, [])
画像コンポーネントと画像の自動最適化
バージョン10.0.0以降、Next.js には Image Component and Automatic Image Optimization が組み込まれています。
Next.js のイメージコンポーネントである next/image
は、HTML の<img>
要素を拡張したもので、現代のウェブ用に進化しています。
自動画像最適化では、ブラウザがサポートしている場合、WebP などの最新フォーマットで画像をリサイズ、最適化して提供することができます。これにより、ビューポートが小さいデバイスに大きな画像を配信することがなくなります。また、Next.js は将来の画像フォーマットを自動的に採用し、それらのフォーマットをサポートするブラウザに提供することができます。
Next.js は、ビルド時に画像を最適化するのではなく、ユーザーのリクエストに応じてオンデマンドで画像を最適化します。10 枚の画像でも 1,000 万枚の画像でも、ビルド時間が長くなることはありません。
import Image from "next/image"
export default function Home() {
return (
<>
<h1>My Homepage</h1>
<Image src="/me.png" alt="Picture of the author" width={500} height={500} />
<p>Welcome to my homepage!</p>
</>
)
}
環境変数
Next.js は、Create React App と同様に、.env
環境変数をサポートしています。主な違いは、クライアントサイドで環境変数を公開する際に使用するプレフィックスです。
- プレフィックスが
REACT_APP_
の環境変数をすべてNEXT_PUBLIC_
に変更します。 - サーバーサイドの環境変数は、ビルド時やAPI Routesで公開されます。
検索エンジンの最適化
ほとんどの Create React App の例では、適切な SEO のためのmeta
タグの追加を支援するために、react-helmet
を使用しています。Next.js では、next/head
を使って、<head />
要素にmeta
タグを追加しています。例えば、ここでは Create React App を使った SEO コンポーネントを紹介しています。
import { Helmet } from 'react-helmet'
export default function SEO({ description, title, siteTitle }) {
return (
<Helmet
title={title}
titleTemplate={siteTitle ? `%s | ${siteTitle}` : null}
meta={[
{
name: `description`,
content: description,
},
{
property: `og:title`,
content: title,
},
{
property: `og:description`,
content: description,
},
{
property: `og:type`,
content: `website`,
},
{
name: `twitter:card`,
content: `summary`,
},
{
name: `twitter:creator`,
content: twitter,
},
{
name: `twitter:title`,
content: title,
},
{
name: `twitter:description`,
content: description,
},
]}
/>
)
}
また、Next.js を使った同じ例を以下に示します。
import Head from 'next/head'
export default function SEO({ description, title, siteTitle }) {
return (
<Head>
<title>{`${title} | ${siteTitle}`}</title>
<meta name="description" content={description} />
<meta property="og:type" content="website" />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:site_name" content={siteTitle} />
<meta property="twitter:card" content="summary" />
<meta property="twitter:creator" content={config.social.twitter} />
<meta property="twitter:title" content={title} />
<meta property="twitter:description" content={description} />
</Head>
)
}
Single-Page App (SPA)
既存の Create React App を Next.js に移行してシングルページアプリを維持したい場合、古いアプリケーションのエントリーポイントをpages/[[...app]].js
という名前の Optional Catch-All Route に移動することができます。
import { useState, useEffect } from 'react'
import CreateReactAppEntryPoint from '../components/app'
function App() {
const [isMounted, setIsMounted] = useState(false)
useEffect(() => {
setIsMounted(true)
}, [])
if (!isMounted) {
return null
}
return <CreateReactAppEntryPoint />
}
export default App
Ejected Create React App
Create React App をイジェクトした場合、以下の点を考慮する必要があります。
- CSS や Sass などのアセット用にカスタムファイルローダーを設定している場合、これはすべて Next.js に組み込まれています。
- JavaScript の新機能(例:Optional Chaining)やPolyfillsを手動で追加している場合は、Next.js にデフォルトで含まれているものを確認してください。
- カスタムのコード分割設定をしている場合は、それを削除することができます。Next.js には、ページ単位での自動コード分割機能があります。
- Next.js では、フレームワークから退出することなく、PostCSS の設定をカスタマイズすることができます。
- Next.js のデフォルトのBabel configとWebpack configを参照して、何がデフォルトで含まれているかを確認してください。
詳細を学ぶ
Next.js の詳細については、starter tutorialをご覧ください。ご不明な点や、このガイドがうまくいかなかった場合は、GitHub Discussionsのコミュニティまでお気軽にお問い合わせください。
Discussion