🚀

【Next.js和訳】Migrating to Next.js/Migrating from CRA

10 min read

この記事について

株式会社 UnReact はプロジェクトの一環としてNext.js ドキュメントの和訳を行っています。

この記事は、Migrating to Next.js/Migrating from Create React Appの記事を和訳したものです。

記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。

Migrating from Create React App

このガイドでは、イジェクトされていない既存の Create React App プロジェクトから Next.js に移行する方法を理解することができます。Next.js に移行することで、以下のことが可能になります。

他にもいろいろあります。それでは、移行を完了するための一連の手順を説明します。

package.json のアップデートと dependencies

Next.js に移行するための最初のステップは、package.jsonと依存関係を更新することです。以下の作業を行います。

  • react-scriptsを削除します(ただし、reactreact-domは残します)。React Router を使用している場合は、react-router-domも削除します。
  • nextをインストールします。
  • Next.js 関連のコマンドをscriptsに追加します。一つは next dev で、これは localhost:3000 で開発サーバーを動かすものです。また、プロダクションビルドを作成・開始するために、next buildnext startも追加しましょう。

以下は、package.jsonの例です。

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 filepublicディレクトリを使用していますが、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 には、CSSSassCSS-in-JSのサポートが組み込まれています。

Create React App を使えば、React コンポーネント内で.cssファイルを直接インポートすることができます。Next.js でも同じことができますが、これらのファイルはCSS Modulesである必要があります。グローバルなスタイルについては、グローバルスタイルシートを追加するために、カスタム _app.jsが必要になります。

Web API への安全なアクセス

クライアントサイドでレンダリングするアプリケーション(Create React App など)では、windowlocalStoragenavigatorなどの 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 コンポーネントを紹介しています。

src/components/seo.js
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 を使った同じ例を以下に示します。

src/components/seo.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 に移動することができます。

pages/[[...app]].js

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 configWebpack configを参照して、何がデフォルトで含まれているかを確認してください。

詳細を学ぶ

Next.js の詳細については、starter tutorialをご覧ください。ご不明な点や、このガイドがうまくいかなかった場合は、GitHub Discussionsのコミュニティまでお気軽にお問い合わせください。

Discussion

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