🚴‍♂️

Next.js v11 で新規プロジェクトを作るときの備忘録

2021/06/26に公開

はじめに

明日の自分のために、Next.js v11でcreate-next-app直後に行っている開発前の下準備の備忘録になります。
create-next-appでは自分で作ったテンプレートをgit環境に置くことでテンプレートとして利用することもできます。

$ yarn create next-app PROJECT_NAME -e gitrepositoryURL

https://nextjs.org/docs/api-reference/create-next-app

なお以下は手動でTypeScriptを入れていきますが、Next.js側でもTypeScriptの初期設定を行ったテンプレートも用意してくれていますので、こちらの方が早いという噂もあります。。
ただテンプレートには不要なコンポーネントも多いので私は手動で対応しています。

npx create-next-app --ts
# or
yarn create next-app --typescript

https://nextjs.org/docs/basic-features/typescript

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

何はともあれプロジェクトの作成。

$ yarn create next-app PROJECT_NAME
or
$ npx create-next-app PROJECT_NAME

2. pages配下、styles配下のソースコードを/srcディレクトリに移動

ディレクトリ構成には好みもあるかと思いますが、私は/srcディレクトリにまとめるようにしています。

$ cd PROJECT_NAME
$ mkdir src && mv pages src/pages & mv styles src/styles

3. TypeScriptのインストール

TypeScriptの構成ファイルをインストールします。

$ yarn add -D typescript @types/react @types/react-dom @types/node
# or
$ npm i -D typescript @types/react @types/react-dom @types/node

4. .js拡張子のファイルを.ts.tsx拡張子に変更

/srcディレクトリ配下にある.js拡張子のファイルを.ts.tsx拡張子に変更します。

$ find src/pages -name "_app.js" -or -name "index.js" | sed 'p;s/.js$/.tsx/' | xargs -n2 mv & \\
  find src/pages/api -name "*.js" | sed 'p;s/.js$/.ts/' | xargs -n2 mv

5. tsconfig.jsonnext-env.d.tsファイルの追加

この時点で開発サーバーを起動するとNext.jsが自動的にtsconfig.jsonnext-env.d.tsを作成してくれます。

$ yarn dev
or
$ npm run dev

6. TypeScriptの設定を変更

strictモードをtrueに変更します。

tsconfig.json
"strict": false,
->
"strict": true,

また、この部分は好みですがbaseURLオプションに.を追加します。
.を追加することでTypeScriptファイル内でimportする際にsrc/hogehogeといった形でプロジェクトルートからのパスで記載することができます。

tsconfig.json
{
  "compilerOptions": {
    // add
    "baseUrl": "."
  }
}

7. _app.tsxファイルの修正

TypeScriptの型情報を付与していく作業と、関数をアロー関数に変更します。

src/pages/_app.tsx
import { AppProps } from 'next/app';
import '../styles/globals.css';

const MyApp = ({ Component, pageProps }: AppProps): JSX.Element => {
  return <Component {...pageProps} />;
};

export default MyApp;

8. index.tsxファイルの修正

同じくこちらも修正していきます。

src/pages/index.tsx
import Head from 'next/head';
import Image from 'next/image';
import { NextPage } from 'next';
import styles from '../styles/Home.module.css';

const Home: NextPage = () => {
//
// この中身はそのまま利用します。
//
};

export default Home;

9. api/hello.tsファイルの修正

利用しないことも多いですが一応こちらも修正しておきます。

src/pages/api/hello.ts
import type { NextApiRequest, NextApiResponse } from 'next';

type Data = {
  name: string;
};

const hello = (req: NextApiRequest, res: NextApiResponse<Data>) => {
  res.status(200).json({ name: 'John Doe' });
};

export default hello;

10. カスタムドキュメントの追加

metaタグ類やWebフォントの利用などに必要となるカスタムドキュメントファイルを追加します。

$ touch src/pages/_document.tsx

https://github.com/vercel/next.js/pull/28515

src/pages/_document.tsx
import { Html, Head, Main, NextScript } from 'next/document';

const MyDocument = () => {
  const url = '<https://example.com>';
  const title = 'Demo Next.js';
  const description = 'Demo of Next.js';

  return (
    <Html lang="ja-JP">
      <Head>
        {/* Change the contents of `<Head>` as needed. */}
        <meta name="description" content={description} />
        <meta name="theme-color" content="#333" />
        <meta property="og:type" content="website" />
        <meta property="og:title" content={title} />
        <meta property="og:url" content={url} />
        <meta property="og:description" content={description} />
        <meta property="og:site_name" content={title} />
        <meta property="og:image" content={`${url}/ogp.png`} />
        <meta name="twitter:card" content="summary_large_image" />
        <meta name="format-detection" content="telephone=no" />
        <link rel="apple-touch-icon" href="/apple-touch-icon.png" />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
};

export default MyDocument;

以下従来のClass componentで記載の場合

src/pages/_document.tsx
import React from 'react'
import Document, { Html, Head, Main, NextScript } from 'next/document'

interface MyDocumentInterface {
  url: string
  title: string
  description: string
}

class MyDocument extends Document implements MyDocumentInterface {
  url = '<https://example.com>'
  title = 'Demo Next.js'
  description = 'Demo of Next.js'

  render(): JSX.Element {
    return (
      <Html lang="ja-JP">
        <Head>
          {/* Change the contents of `<Head>` as needed. */}
          <meta name="description" content={this.description} />
          <meta name="theme-color" content="#333" />
          <meta property="og:type" content="website" />
          <meta property="og:title" content={this.title} />
          <meta property="og:url" content={this.url} />
          <meta property="og:description" content={this.description} />
          <meta property="og:site_name" content={this.title} />
          <meta property="og:image" content={`${this.url}/ogp.png`} />
          <meta name="twitter:card" content="summary_large_image" />
          <meta name="format-detection" content="telephone=no" />
          <link rel="apple-touch-icon" href="/apple-touch-icon.png" />
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

export default MyDocument

11. Sassのインストール

Sassを利用する場合に限りますが、必要に応じてSassをインストールします。

$ yarn add -D sass

12. 起動スクリプトの調整

同じネットワーク内の他のPCやスマートフォンから開発サーバーに接続して閲覧確認ができるよう、開発サーバーの起動スクリプトを調整します。

packages.json
{
  ...
  "scripts": {
    "dev": "next dev --hostname 0.0.0.0",
  },
  ...
}

13. Prettierの設定

プロジェクトによりますが、Prettierの設定ファイルを追加しています。

$ touch .prettierrc
.prettierrc
{
  "trailingComma": "all",
  "semi": true,
  "singleQuote": true,
  "printWidth": 100,
  "tabWidth": 2
}

14. ESLint

Next.js v11からESLintはNext.jsで追加されたものを使うようにしています。
チームやプロジェクトによって随時対応。。。

15. その他

Storybook、Jestはプロジェクトによって随時追加。。。

GitHubで編集を提案

Discussion