JavaScript(TypeScript)開発環境の構築はセットアップすることが多くて大変ですよね。。。
ESLintを設定したり、Prettierを設定したり、テストを設定したりとやることが尽きません。
本記事のタイトルを見るだけでもその多さに疲れてしまいます。
ただでさえやることが多いのに最初の環境構築の手順なんかは大体忘れているので、環境構築のたびにいろんなサイトを横断してやり方を調べる・思い出すことに時間を費やしてしまっています。
そこで今回は自身の備忘録もふまえて、よく使いそうな構成の環境構築手順をまるっとまとめて記していきます。
- Next.js + TypeScriptの環境を構築できる
- Chakra UIとChakra UIカスタムテーマを使用する環境を構築できる
- ESLint, Prettier, commitlintによるフォーマット・チェックができる
- Jest + React Testing Libraryでユニットテストを実行できる
- husky + lint-stagedによるフォーマット・コードチェック・テストの自動化ができる
- WebStorm(JetBrains製IDE)を利用した環境構築と設定ができる
プロジェクト作成
まずは新規プロジェクトの作成。
ここではWebStormを使いますので、別のエディタやIDEを使用している場合はこの手順は無視してそれぞれのやり方でプロジェクトを作成してください。
Githubなどのリポジトリがすでにあるかどうかでプロジェクト作成方法が変わります。
新規作成
リポジトリを作成していない場合はこちら。
下記画像を参考に左から順に実施します。
クリックすると拡大できます。
リポジトリからクローン
すでにあるリポジトリからクローンしてプロジェクトを作成したい場合はこちら。
下記画像を参考に左から順に実施します。
クリックすると拡大できます。
Gitの設定
プロジェクト全体のソースコードを管理するためにgitを設定します。
root
で下記のコマンドを実行します。
git init
コマンドはIDE下部のターミナルからも実行可能です。
以降のコマンドはすべてIDEのターミナルから実行するものとします。
ついでに空の.gitignore
も作っておきます。
以降は必要に応じてリポジトリ管理不要なものを追記していきましょう。
これでプロジェクトの作成は完了!
Next.js + TypeScript
続いてNext.jsの環境構築を行います。
公式で用意されている便利なセットアップコマンドがあるのでそれを利用します。
セットアップ
root
で下記のコマンドを実行します。
npx create-next-app@latest --ts next
- TypeScriptを使用するので
--ts
オプションを指定しています。 - 最後の引数がプロジェクト名(フォルダ名)で、上記では
next
です。
処理が完了すると以下のように表示されます。
この状態でnpm run dev
を実行しても動きますが、WebStormからも実行できるように設定を施します。
下記画像を参考に左から順に実施します。
クリックすると拡大できます。
設定後、実行ボタンを押してlocalhost:3000へアクセスして画面が表示されればOK!
フォルダ構成の変更
create-next-appで作成したフォルダの構成は以下のようになっています。
next/
├── .next/
├── node_modules/
├── pages/
├── public/
└── styles/
next
直下にソースコードがずらっと並んでしまい見通しが悪いです。
そのため、src
を作成してpages
とstyles
を移動します。
変更後のフォルダ構成は以下のようになります。
next/
├── .next/
├── node_modules/
├── public/
└── src/
├── pages/
└── styles/
Next.jsアプリケーション全体のフォルダ構成については以下の記事で紹介しています。
パスのエイリアス設定
フォルダ構成の変更のついでに、モジュールパスのエイリアスを設定しておきます。
next/tsconfig.json
のcompilerOptions
に以下のように設定を追加します。
{
"compilerOptions": {
...
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
...
}
以降は次のようにパスを指定できます。相対パスを書かなくて済むので楽♪
import {Sample} from '@/pages/test/Sample'
以上でNext.jsの設定は完了!
Prettier
コードフォーマットを行うためにPrettierを導入します。
セットアップ
まずはインストール。root
で下記のコマンドを実行します。
npm i -D prettier
続いてフォーマットルールの設定。root
に.prettierrc.toml
(ファイル形式はお好みでOK)を作成します。
root/
├── next/
├── node_modules/
├── .prettierrc.toml <- 追加
設定ファイルの中身は以下。公式と同じように設定。
trailingComma = 'es5'
tabWidth = 2
semi = false
singleQuote = true
各ファイル形式ごとの書き方は下記リンク先のものをベースにすればOKです。
WebStormの設定
WebStorm上でPrettierによるフォーマットを行うために、以下のように設定しておきます。
Prettierによるコードフォーマット対象とするファイル形式を増やしたい場合は、「次のファイルに実行」の入力欄に拡張子を追加しておく必要があります。
これでPrettierの設定は終わり。
ESLint
コードの静的検証にはESLintを使用します。
セットアップ
まず最初にcreate-next-app
を実行した際にnext
配下に.eslintrc.json
が作成されていますので、それを削除します。
next/
├── .next/
├── node_modules/
├── public/
├── src/
├── .eslintrc.json <- 削除
root
でインストールコマンドを実行します。
npm i -D eslint eslint-config-prettier
Next.jsアプリケーション内で適用するESLintルールを作成します
初期設定に関しては対話形式で作成するのが個人的にわかりやすいと思います。next
で下記コマンドを実行して質問に回答していきましょう。
npx eslint --init
You can also run this command directly using 'npm init @eslint/config'.
Need to install the following packages:
@eslint/create-config
Ok to proceed? (y) y
? How would you like to use ESLint? …
To check syntax only
❯ To check syntax and find problems
To check syntax, find problems, and enforce code style
? What type of modules does your project use? …
❯ JavaScript modules (import/export)
CommonJS (require/exports)
None of these
? Which framework does your project use? …
❯ React
Vue.js
None of these
? Does your project use TypeScript? › Yes
? Where does your code run? … (Press <space> to select, <a> to toggle all, <i> to invert selection)
✔ Browser
Node
? What format do you want your config file to be in? …
JavaScript
❯ YAML
JSON
eslint-plugin-react@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
? Would you like to install them now with npm? › Yes
...
中略
...
Successfully created .eslintrc.yml file
対話形式での処理が完了後、next/.eslintrc.yml
が作成されます。
ファイルの中身は以下のようになっているはずです。
env:
browser: true
es2021: true
extends:
- eslint:recommended
- plugin:react/recommended
- plugin:@typescript-eslint/recommended
parser: '@typescript-eslint/parser'
parserOptions:
ecmaFeatures:
jsx: true
ecmaVersion: latest
sourceType: module
plugins:
- react
- '@typescript-eslint'
rules: {}
設定内容を以下のように修正して完了です!
env:
browser: true
es2021: true
extends:
- next/core-web-vitals
- eslint:recommended
- plugin:react/recommended
- plugin:@typescript-eslint/recommended
- prettier
parser: '@typescript-eslint/parser'
parserOptions:
ecmaFeatures:
jsx: true
ecmaVersion: latest
sourceType: module
plugins:
- react
- '@typescript-eslint'
rules: {
react/react-in-jsx-scope: off
}
WebStormの設定
WebStorm上のコードチェックにESLintを使用するように設定します。
これでESLintの設定は終わり。
環境変数
特別な設定はしないで、Next.js標準を使用します。
ちなみにprocess.env
に展開される値にはJavaScriptのオブジェクトのように動的にはアクセスできないみたいです。知らなかった。。。
const name = 'NEXT_PUBLIC_TEST'
const test = process.env[name] // この方法では'NEXT_PUBLIC_TEST'の値は取得できない
Jest + React Testing Library
ユニットテストができるように設定をします。
選択肢はいくつかありますが、公式に記載のあるJest + React Testing Libraryの構成でいきます。
本項の手順は公式の手順を基本としていますが、エラーになる箇所がそこそこあったため、エラー解消が確認できた手順・設定にしています。
実行環境によっては違うエラーが発生するかもしれません。
セットアップ
next
でインストールコマンドを実行
npm i -D jest @testing-library/react @testing-library/jest-dom jest-environment-jsdom ts-jest
next/jest.setup.js
next/jest.config.js
の2つの設定ファイルを作成します。
import '@testing-library/jest-dom'
/* eslint-disable @typescript-eslint/no-var-requires */
const nextJest = require('next/jest')
const { compilerOptions } = require('./tsconfig.json')
const { pathsToModuleNameMapper } = require('ts-jest')
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
})
// Add any custom config to be passed to Jest
const customJestConfig = {
// Add more setup options before each test is run
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
// if using TypeScript with a baseUrl set to the root directory then you need the below for alias' to work
moduleDirectories: ['node_modules', '<rootDir>/'],
testEnvironment: 'jest-environment-jsdom',
preset: 'ts-jest',
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths),
}
// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig)
next/package.json
にtest
スクリプトを追加します。
...
"scripts": {
...
"test": "jest"
},
...
ユニットテスト用のフォルダnext/__tests__
を作成します。
next/
├── .next/
├── __tests__ <- 追加/
├── node_modules/
├── public/
└── src/
├── pages/
└── styles/
__tests__/sample.tsx
を作成して、公式と同様にテストを作成。
import { render, screen } from '@testing-library/react'
import Home from '@/pages/index'
describe('Home', () => {
it('renders a heading', () => {
render(<Home />)
const heading = screen.getByRole('heading', {
name: /welcome to next\.js!/i,
})
expect(heading).toBeInTheDocument()
})
})
npm run test
を実行してテストが成功すれば問題なし。
/bin/zsh % npm run test
> next@0.1.0 test
> jest
PASS __tests__/sample.tsx
Home
✓ renders a heading (61 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.705 s, estimated 1 s
Ran all test suites.
これでユニットテストのセットアップは完了!
husky + lint-staged
ESLint・Prettier・ユニットテストの自動化をしていきます。
使用するツールはhusky, lint-stagedの2つです。
- husky
-
コミットやプッシュなどのgit操作をトリガーに、設定したコマンドなどの処理を実行するツール。
- lint-staged
-
ステージング済のファイルを対象に、設定したコマンドなどの処理を実行するツール。筆者は勘違いしていましたが、ステージング操作をトリガーになにか処理を実行するためのツールではありません。
セットアップ
とにもかくにもまずはインストール。root
で下記コマンドを実行します。
npm i -D husky lint-staged
lint-stagedでステージング済のファイルに対して以下を実行するように設定します。
- Prettierによるコードフォーマット
- ESLintによるコードチェック
root/.lintstagedrc.yml
を以下の内容で作成します。
'*.{js,jsx,ts,tsx}':
- prettier --write
- eslint --max-warnings 0
これでlint-stagedを利用してステージング済のファイルに対してPrettier, ESLintが実行できるようになりました。
続いてhuskyの設定です。
コミット前に以下を行い、エラーがある場合はコミットを中断させます。
- Prettierによるコードフォーマット
- ESLintによるコードチェック
- Jestによるテスト実行
root/package.json
に以下を追加します。
...
"scripts": {
"test": "npm test --prefix next",
"prepare": "husky install"
},
...
下記のコマンドをroot
で実行します。
npx husky install
npx husky add .husky/pre-commit "npx lint-staged"
npx husky add .husky/pre-commit "npm test"
npx lint-staged
を実行することで下記2つを実行しています。
- Prettierによるコードフォーマット
- ESLintによるコードチェック
これでコミット時にPrettier, ESLint, テストを実行するようになりました!
コミットメッセージ関連
コミットメッセージ関連の便利なツールを導入していきます。
ESLintやユニットテストに比べて、設定することでかえって面倒になる場合もあるので注意!
commitlint
コミットメッセージ用の検証ツールです。
ルールに従ったコミットメッセージでない場合にコミットを中断させることができます。
root
でインストール。
npm i -D @commitlint/cli @commitlint/config-conventional
root/.commitlintrc.yml
を以下の内容で作成します。
extends:
- '@commitlint/config-conventional'
本記事で使用するルールはConventional Commitsという仕様に従ったもので、
コミットメッセージを以下の形式で書く必要があります。
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
詳しくは下記のリンク(日本語)をご覧ください。
あとはhuskyを使って、コミット時にコミットメッセージの検証を実行するようにします。
npx husky add .husky/commit-msg "npx commitlint --edit"
ルールに従っていないメッセージでコミットしてみると無事エラーとなり、コミットが中断されるようになりました。
/bin/zsh % git commit -am "add commitlint"
...
⧗ input: add commitlint
✖ subject may not be empty [subject-empty]
✖ type may not be empty [type-empty]
✖ found 2 problems, 0 warnings
ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint
husky - commit-msg hook exited with code 1 (error)
commitlintはこれでOK!
Git commit template (WebStormプラグイン)
commitlintで検証するのは良いことですが、慣れるまではルールに従ったコミットメッセージを作るのは大変かもしれません。
そのためコミットメッセージを作成するサポートツールを導入します。
※WebStorm(JetBrains製IDE)向けのプラグインです。
JetBrains製IDEを使用していない方はcommitizenというものがnpmで提供されてますので興味があればやってみても良いかもしれません。
WebStormのプラグイン画面からインストールします。
プラグインのインストール完了後、WebStormを再起動します。
再起動後、プロジェクトを開いてコミット画面を見ると新しいアイコンが追加されています。
そこから画面に沿って進めていけば良い感じにコミットメッセージが作成できます。
Chakra UI
React向けのコンポーネントライブラリです。
すでに用意されている豊富なコンポーネントを利用してフロントエンドを実装できます。
基本的にはCSSファイルを用意することなく実装できるというのもメリットのひとつです。
セットアップ
next
でインストールを実施。
npm i @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^6
スタイル関連はCSSを使用せずにChakra UIで管理したいため、カスタムテーマを使用できるように実装していきます。
カスタムテーマ用のフォルダnext/src/theme
を作成します。
next/
├── .next/
├── __tests__ /
├── node_modules/
├── public/
└── src/
├── pages/
├── styles/
└── theme <- 追加/
以降は作成したtheme
配下にコードを作成していきます。階層構造になっている場合はフォルダも合わせて作成します。
export const colors = {
sample: {
gray: '#D8D8D8',
},
}
export const fonts = {}
export const styles = {
global: {
body: {
bgColor: 'sample.gray',
},
},
}
export const Button = {
variants: {
orange: {
bg: 'orange',
color: 'white',
},
},
}
import { extendTheme } from '@chakra-ui/react'
import { colors } from '@/theme/colors'
import { styles } from '@/theme/styles'
import { fonts } from '@/theme/fonts'
import { Button } from '@/theme/components/button'
const customTheme = extendTheme({
colors,
components: {
Button,
},
fonts,
styles,
})
export default customTheme
Chakra UIが提供するコンポーネントをプロジェクト内で使用できるように、ChakraProvider
をnext/src/pages/_app.tsx
に追加します。
import '../styles/globals.css'
import type { AppProps } from 'next/app'
import { ChakraProvider } from '@chakra-ui/provider'
import customTheme from '@/theme/customTheme'
function MyApp({ Component, pageProps }: AppProps) {
return (
<ChakraProvider theme={customTheme}>
<Component {...pageProps} />
</ChakraProvider>
)
}
export default MyApp
実際にChakra UIのコンポーネントが使えるかnext/src/pages/index.tsx
を編集して確認しておきましょう。
import type { NextPage } from 'next'
import { Button, Heading } from '@chakra-ui/react'
const Home: NextPage = () => {
return (
<>
<Heading>
Welcome to <a href="https://nextjs.org">Next.js!</a>
</Heading>
<Button variant={'orange'}>test</Button>
</>
)
}
export default Home
実行して、localhost:3000が以下のように表示されていればOKです!
無事Chakra UIを使用できるようになりました!
ちなみに、src/styles
は必要に応じて削除してしまっても大丈夫です。
カスタムテーマの自動補完
自身で作成したカスタムテーマの設定項目は自動補完させることができます。
自動補完定義を生成するためのツールをnext
でインストールします。
npm install -D @chakra-ui/cli
続いて下記のコマンドを実行します。
npx chakra-cli tokens src/theme/customTheme.ts
実行後はカスタムテーマの定義が内部的に生成され、自動補完できるようになります。
カスタムテーマを更新するたびに毎回上記のコマンドは必要となります。
そこでhuskyを使って少しでも自動化しておきます。
next/package.json
root/package.json
それぞれに以下のスクリプトを追加します。
...
"scripts": {
…
"gen:theme-typings": "npx chakra-cli tokens src/theme/customTheme.ts"
},
...
...
"scripts": {
…
"gen:theme-typings": "npm run gen:theme-typings --prefix next"
},
...
root
で下記のコマンドを実行して、huskyに設定を追加します。
npx husky add .husky/post-merge "npm run gen:theme-typings"
npx husky add .husky/post-checkout "npm run gen:theme-typings"
これでチェックアウト時とマージ実行時(≒pull実行時)に自動補完定義の生成処理が実行されるようになりました。
自動補完定義の設定も完了です!
最後に
以上で本記事における環境構築は完了です!
最近のJavaScript(TypeScript)の開発環境は環境構築だけで一苦労ですね。
正直「ここまでするなら別言語のほうが良いのでは?」と思ったりもしています。
とはいえ、まだしばらくはJavaScript(TypeScript)構成は使われると思いますので、毎回の環境構築で時間をかけたくない人の役に立てたら嬉しいです。