>Develop>React>Next.jsの開発環境構築

Next.jsのプロジェクトを作成

–tsオプションでTypeScript向けのプロジェクトを作成できる。

$ npx create-next-app@latest --ts next-sample

開発サーバーを立ち上げる。

$ npm run dev

ビルドする。

$ npm run build

ビルドしたプログラムを元にサーバーを立ち上げる。

$ npm run build

描画方法

Next.jsでは描画をページ毎に切り替えることができる。描画の方法は、下記の4つある。

  • CSR(Client Side Rendering)
  • ISR(Incremental Static Rendering)
  • SSG(Single Static Site Generation)
  • SSR(Server Side Rendering)

CSR

ビルド時にはデータ取得をせず、ページを描画し、保存を行う。ブラウザの初期のレンダリング後に非同期でデータを取得し、追加のデータを描画する。ページを描画するのに必要なデータを後から取得して描画するため、SEOには有効でない。

CSRは、他の描画方法と組み合わせて利用され、初期描画がそこまで重要でなく、リアルタイム性が求められるページに向いている。

ISR

事前にページを生成し、レンダリングしておき、アクセスに応じてページを再度生成して新しいページを生成し、クライアントに送る。また、データの有効期限を設定でき、有効期限が切れた状態でアクセスがあった場合、バックグラウンドで再度getStaticProps関数の実行とページを描画し、サーバーに保存されているページデータを更新する。

SSRと異なり、リクエスト時にサーバー側での処理がないため、レイテンシが高く、且つ最新のデータを元にページを初期描画できる。

SSG

ビルド時にAPIなどからデータを取得し、ページを描画して静的ファイルを生成する。これは、ビルド時にgetStaticProps関数が呼ばれ、この関数内でAPIコールなどを行い、ページの描画に必要なpropsを返却する。このpropsをページコンポーネントに渡して描画する。この描画結果が静的ファイルで保存される。そして、ページにアクセスされたらこの静的ファイルをクライアントへ送り、ブラウザにレンダリングされる。ブラウザで初期にレンダリングされた後は、APIなどからデータを取得し、動的に描画を変化できる。

アクセス時は、静的ファイルをクライアントに返すだけなので、初期のレンダリングは高速である一方、ビルド時のみデータを取得を行うため、初期レンダリングで古いデータが表示される可能性がある。そのため、リアルタイム性が求められるコンテンツには向かず、表示内容が変更されないページや初期レンダリング以降にデータを表示するページに向いている。

SSR

ページのアクセスがある度、サーバーでgetServerSideProps関数を呼び、その結果のpropsを元にページをサーバー側で生成しクライアントに送る。アクセスされる度にサーバーでデータを取得し、描画を行うため、常に最新のデータを元にページの初期描画できる。また、SEOにも有効。一方で、サーバーで一定の処理が必要なため、レイテンシが低くなる可能性がある。

描画手法とデータ取得のタイミング

データ取得に使う関数備考
CSRuseSWRなどの関数ユーザーのリクエスト時にデータを取得(ブラウザ)。
ISRgetStaticPropsビルド時にデータを取得。デプロイ後もバックグラウンドでビルドが行われる。
SSGgetStaticPropsビルド時にデータを取得。
SSRgetServerSidePropsユーザーのリクエスト時にデータを取得(サーバーサイド)。

CSS

styled-componentsは、CSS in JavaScriptというライブラリで、Javascript内にCSSを記述できる。TypeScriptやJavascript、CSS、HTMLなどのコードを1つのコンポーネントにまとめることができる。

$ npm install --save styled-components
$ npm install --save-dev @types/styled-components

next.config.jsに設定を記述する。

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  /* config options here */
  reactStrictMode: true,
  compiler: {
    styledComponents: true,
  }
};

export default nextConfig;

Storybookの環境構築

Storybookは、UIコンポーネントを確認することができるUIカタログ。下記コマンドでインストールし、実行できる。

$ npx sb@latest init

その他のプラグイン等をインストールする。

$ npm install --save-dev @storybook/addon-postcss tsconfig-paths-webpack-plugin @babel/plugin-proposal-class-properties @babel/plugin-proposal-private-methods @babel/plugin-proposal-private-property-in-object tsconfig-paths-webpack-plugin @mdx-js/react

storybookを実行する。

$ npm run storybook

自分の場合は、実行すると下記のエラーが発生した。どうやらPostCSSの設定のフォーマットがviteと互換性がないとのこと。

=> Failed to build the preview
SB_FRAMEWORK_NEXTJS_0003 (IncompatiblePostCssConfigError): Incompatible PostCSS configuration format detected.

Next.js uses an array-based format for plugins which is not compatible with Vite:

// ❌ Incompatible format (used by Next.js)
const config = {
  plugins: ["@tailwindcss/postcss"],
};

Please transform your PostCSS config to use the object-based format, which is compatible with Next.js and Vite:

// ✅ Compatible format (works with Next.js and Vite)
const config = {
  plugins: {
    "@tailwindcss/postcss": {},
  },
};

Original error: Invalid PostCSS Plugin found at: plugins[0]

(@.\postcss.config.mjs)

デフォルトでは、postcss.config.mjsは下記のようになっている。

const config = {
  plugins: ["@tailwindcss/postcss"],
};

export default config;

デフォルトの設定を下記のように書き換えることで解決できた。どうやら配列にすればいいだけみたい。

const config = {
  plugins: {
    "@tailwindcss/postcss": {}
  }
};

export default config;

もう一度、実行(run)すると今度はちゃんと実行できた。

storybook関する記事。

テスト環境の構築

テストに必要なパッケージをインストールする。

$ npm install --save-dev jest @testing-library/react @testing-library/jest-dom jest-environment-jsdom

プロジェクトディレクトリ直下に jest.config.js を作成し、下記を記述する。

const nextJest = require('next/jest')

const createJestConfig = nextJest({ dir: './' })

const customJestConfig = {
  testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/'],
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  testEnvironment: 'jsdom',
}

module.exports = createJestConfig(customJestConfig)

同じくプロジェクトディレクトリ直下に jest.setup.js を作成し、下記を記述する。

import '@testing-library/jest-dom/extend-expect'

package.jsonにテストを実行するためのscriptを記述する。

"scripts": {
    .
    .
    .
    "test": "jest"
  },

tsconfig.json

 "types": [
      "node",
      "jest",
      "@testing-library/jest-dom"
    ],

テストファイルは、.spec.tsx または .text.tsx といった拡張子のファイルで作成しなければならない。 テストファイルので使用する関数などは、Javascriptのテストフレームワークである Jest の公式ドキュメントを参考にする。

パッケージのインストールと設定が終わったら下記コマンドでテストを実行できる。問題なくテストが実行された後はちゃんとテスト結果が表示される。

$ npm run test

> testing@0.1.0 test
> jest

 PASS  components/Input/index.spec.tsx
  Input
    √ should empty in input on initial render (21 ms)                                                                                                 
    √ should show input text (8 ms)                                                                                                                   
    √ should reset when user clicks button (35 ms)                                                                                                    
                                                                                                                                                      
Test Suites: 1 passed, 1 total                                                                                                                        
Tests:       3 passed, 3 total                                                                                                                        
Snapshots:   0 total
Time:        0.88 s, estimated 1 s
Ran all test suites.

その他便利なライブラリ

React Hook Formの

React Hook Formは、フォームのバリデーションを行うライブラリ。

$ npm install react-hook-form

SWR

SWRは、データ取得のためのライブラリ。取得したデータをキャッシュしたり、エラー時に再トライしたり、ネットワークが復帰した際に再度データを更新したりと、データ取得処理に関連した便利なReact Hookのライブラリ。

$ npm install swr

React Content Loader

React Content Loaderは、ローディングのためのプレースホルダーを作成できるライブラリ。

$ npm install react-content-loader
$ npm install --save-dev @types/react-content-loader     

Material Icons

UIライブラリのMatereal UIのコンポーネント。様々なアイコンが用意されている。

$ npm install @mui/material @mui/icons-material @emotion/react @emotion/styled

Next.jsに関する記事。

記事を読んでいただきありがとうございました。

Page Top