技術メモ

プログラミングとか電子工作とか

Next.js (+TypeScript) の初期構築(@2020-09-25)

f:id:ysmn_deus:20200925185828p:plain

去年にNext.jsの学習をしていたのですが、Amplifyとの相性が悪くて(Cognitoの認証周りでたいへん苦労した)使うのを辞めていました。
ただ、久しぶりに色々調べてみると、どうやら公式ドキュメントにもNext.js用のチュートリアルがあるみたいなのでちょっとチャレンジしてみます。
ついでに、ESLint + Prettierまわりも何やら推奨設定が変わってきてるそうなのでその辺にも対応した防備録的な記事を目指します。
(また来年新しい記事を書いてそう・・・)
下記は全てWindows環境で行っています。

必要最低限の環境構築

まず最初にこの記事を見てる方は大丈夫だと思うんですが、下記の環境は整えて下さい
章タイトルから察する方はプロジェクト構築へ飛ばして読んで下さい。

  • Node.js(v10.x 以上)
  • npm(v5.x 以上)、後々yarnを使いますが、自分はWindows環境なので一番最初にnpxを使います。
    この記事を参考にする人はついでにyarnも入れといて下さい。
  • git(v2.14.1以上)

上記が整っていれば最初のセットアップは進める事が出来ると思います。

プロジェクト構築

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

Next.jsのプロジェクトを作成します。
LinuxMac環境では

yarn create next-app プロジェクト名

でも作成可能だと思いますが、WindowsはNodeのパスに半角スペースが入ってる人が多いと思いますのでnpxでプロジェクトを作成します。

npx create-next-app next-amplified

プロジェクト名はAmplifyのドキュメントに習ってnext-amplifiedにしてますが、なんでもいいです。
とりあえず問題無く動くか確認しておきたいので、Next.jsプロジェクトを実行してみます。

cd next-amplified
yarn dev

http://localhost:3000にアクセスして問題無く表示されれば大丈夫です。

TypeScriptのセットアップ

tscのインストール

もしTypeScriptのコンパイラがまだグローバルにインストールされてない場合はインストールして置いて下さい。

npm install -g typescript

tsconfig.jsonの作成

プロジェクトのルートディレクトリ(この場合はnext-amplified直下)にtsconfig.jsonを作成します。

tsc --init

上記のコマンドでtsconfig.jsonが作成されます。
最初は別に空ファイルでも良いんですが、この辺は好みです。

開発に必要なライブラリの追加

あとは必要な依存ライブラリを入れておきます。

yarn add -D typescript @types/react @types/node

試しに動かしてみる

上記までで多分動きます。
試しにpagesに入ってるファイルをTypeScriptのファイルに変更してみます。
めんどくさいのでpages/index.jsのみをpages/index.tsxに名前を変更します。
特に他の設定無しで、yarn devを実行すればhttp://localhost:3000に先ほどと同様のページが表示されているかと思います。
(TypeScriptの設定がおかしければ、ここでコンパイルされずに表示されないので)

整理する

とりあえずコンパイルまでは良さそうなので一旦ファイルを整理します。
pagesディレクトリはsrcディレクトリを作成してその直下に配置することにします。
(Next.jsのv9からデフォルトでsrc直下でも認識するようになったようです。)
ついでにstylesは削除しています。
やっぱり後で必要だったので残します

mkdir src
mv pages src

あと、api_app.jsも今は不要なのでいったん消します。

Remove-Item .\src\pages\api\ -Recurse
Remove-Item .\src\pages\_app.js 

色々消してコンパイルが通らなくなるので、index.tsxも編集しておきます。

import React from 'react'

export default function Home() {
  return (
    <div>hoge</div>
  )
}

とりあえずここまでで問題無いか実行してみます。

yarn dev

問題無ければ、Linterの設定などに行きましょう。

ESLint + Prettierの設定

構成

以前はESLintのプラグインでPrettierを走らせていたのですが、下記の記事でも紹介されているとおり公式の推奨が明示されました。

Prettier と ESLint の組み合わせの公式推奨が変わり plugin が不要になった

よって、この設定に従いprettier-eslintを利用してPrettier → ESLintと走るような環境を構築します。
何はともあれESLintとPrettierをセットアップします。

(余談ですが、この辺からIDEを利用した方が色々補完が効いて楽かもしれません)

ESLint

ESLintのインストール

ESLintをTypeScriptで走るようにセットアップしていきます。
この辺は昔と変わらず、素直にインストールします。

yarn add -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react

eslintをグローバル環境でセットアップしてる人は、適宜って感じです。

ESLintの設定

ESLintの設定ファイル.eslintrc.jsをプロジェクトのルートディレクトリに置いておきます。
こちらも、以前の設定と変更無しです。

module.exports = {
  env: {
    browser: true,
    node: true,
    es6: true
  },
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true
    },
    sourceType: "module"
  },
  plugins: [
    "react",
    '@typescript-eslint'
  ],
  extends: [
    "eslint:recommended",
    "plugin:react/recommended",
    'plugin:@typescript-eslint/recommended',
  ],
  rules: {
  },
  overrides: [
    {
      'files': ["**/*.tsx"],
      'rules': {
        'react/prop-types': 'off'
      }
    }
  ]
};

ESLintが走る用のコマンドをpackage.jsonに記載しておきます。

  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "eslint --ext .ts,.js,.tsx,.jsx src/**/*"
  },

チェックする対象は全てsrcディレクトリ内に収まると思うのでこうしておきます。
試しにsrc/pages/index.tsxにわざとセミコロンを付けてESLintでチェックしてみます。

import React from 'react'

export default function Home() {
  return (
    <div>hoge</div>
  )
};
yarn lint

error Unnecessary semicolon @typescript-eslint/no-extra-semiが出てる筈です。
良さそうなのでついでにfixも試してみます。

yarn lint --fix

おそらくセミコロンが消滅したと思います。
ESLintのセットアップは大丈夫そうです。

Prettier

ESLintとPrettierの競合を解消する方法は数種類ありますが、今回は最近TLで見かけたPrettier公式の推奨設定を参考にします。
(なにはともあれ、公式の推奨に従っておくのが賢い筈です)

prettier.io

Prettierのインストール

とりあえずPrettier、eslint-config-prettierをインストールします。

yarn add -D prettier eslint-config-prettier

とりあえずPrettierが動作するか試してみます。index.tsxの最後に改行を入れまくるなどしてフォーマッタで修正されるであろう形にしてみて下さい。
その後

prettier --write "src/**/*.{js,jsx,ts,tsx}"

で修正されるかチェックします。問題無ければPrettierの設定は完了しているはずです。

eslint-config-prettierの設定

PrettierとESLintの競合を解消するために.eslintrc.jsを編集します。

~
  extends: [
    "eslint:recommended",
    "plugin:react/recommended",
    'plugin:@typescript-eslint/recommended',
    "prettier",
    "prettier/@typescript-eslint",
    "prettier/react",
  ],
~

ESLintのextendsの設定は上から順に適応され、後ろの方で上書きされていきます。
なので

~
  extends: [
    [prettier以外のプラグインの設定],
    "prettier",
    "prettier/[対応されていプラグイン]",
  ],
~

という順番で記載することにより、競合が解消されるようです。
(ただし、この辺は理解が曖昧なので、もし挙動が異なっていたら後々修正します。)

ESLint + Prettier

たぶん上記まで対応はOKの筈なので、ESLintとPrettierが両方走るスクリプトを追加します。
ESLintとPrettierを両方実行するために、npm-run-allをインストールします。

yarn add -D npm-run-all

このライブラリでpackage.jsonに記載のあるscriptsを順次/並列実行できるようになります。

~
    "fix": "run-s fix:eslint fix:prettier",
    "fix:eslint": "eslint --ext .ts,.js,.tsx,.jsx src/**/* --fix",
    "fix:prettier": "prettier --check --write \"src/**/*.{js,jsx,ts,tsx}\""
~

これでyarn fixでeslintとprettierが走るようになりました。

こまかいこと

Prettier→ESLintの順番で実行すれば.prettierrc.js要らないんじゃね?とも思いましたが、細かいフォーマット規則も後々付け加えられるので.prettierrc.jsも準備します。
prettierrcjsonで作られてることが多そうなイメージですが、eslintrcもjsで用意してるので一応合わせます。
個人的にセミコロン絶対に許さないマンになりたいのでその辺の設定をしておきます。

module.exports = {
  trailingComma: "es5",
  tabWidth: 2,
  semi: false,
  singleQuote: true,
}

.eslintrc.jsの方にもセミコロン絡みの設定をしておきます。

~
  rules: {
    "semi": ["error", "never", {"beforeStatementContinuationChars": "never"}],
    "semi-spacing": ["error", {"after": true, "before": false}],
    "semi-style": ["error", "first"],
    "no-extra-semi": "error",
    "no-unexpected-multiline": "error",
    "no-unreachable": "error"
  },
~

これで大丈夫です。
この辺まで来たらIDEによってはファイルウォッチャーに登録しても良さそうです。

ちょっと長くなったのでAmplifyに関しては別記事に分けます。