備忘録:TypeScriptにおける環境構築 Linter編
最近、Next.js * TypeScriptに@swc-node/jestを入れたり、適当にやっていたeslintの設定を40行くらいのちょっとしたものに直す機会があった(執筆中に見直して10行ぐらいへった)。
Linter周りは作るたびに同じことを調べている気がするので、多少まとめることにする。
Eslint
module.exports = { env: { browser: true, es2021: true, mocha: true, node: true, 'jest/globals': true, }, extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:jest/recommended', 'plugin:jest/style', 'next/core-web-vitals', 'prettier', ], plugins: ['testing-library'], parser: '@typescript-eslint/parser', parserOptions: { ecmaFeatures: { jsx: true, }, ecmaVersion: 12, sourceType: 'module', }, };
env
envにmochaやjest/globalsを設定すると、jestでテストコードを書くときit
やdescribe
が未定義だと怒られなくなる。nodeは覚えていない。コミットログをみると同タイミングだから@swc-node/jest関連か。
plugin と extends
pluginはルールセットを追加しextendsはルールセットのオンオフなどを行う、これが基本。
しかしextendsでpluginの役割を兼ねることができるため、実際には各configごとに設定方法が違うため、ライブラリごとに公式サイトを見ることになる。 ESLint の Plugin と Extend の違い | blog.ojisan.io
next lint
Next.jsはv11からlintがついてくる。この構成は既存のlintルールの共存が難しい。
自分は主にairbnbとの共存方法を調べていた。自分の結論から言うと、airbnbを捨て、eslint-config-nextに乗り換えることにした。理由は、airbnbの非合理なルールと、next lintによる高速化だった。
まず、airbnbはprefer default export や use before define など時代に合わないルールを採用している。これらを修正するのは、開発効率のためにならない。
次に、next lintの高速化により、2xから3xの高速化ができた。自分は型情報が必要なルールセットをオンにしているため、lintの処理が少し重い。実はeslint-config-nextはルールセット以外にパーサーなども用意していて、これを使うことでかなり高速化された。
パーサなどを変更せずnext.js用のルールセットだけ既存の構成に付け加えることも可能。このためには、extends: ['plugin:@next/next/recommended']を使うとnext.jsの設定だけを追加する。extends:'next'で入る設定は以下で確認できる。
.eslintignore
**/build/ **/public/ **/coverage/ **/node_modules/ **/*.min.js # **/*.config.js **/.*rc.json **/dist/
重いと感じるときは、不要なファイルを見ていることを疑う。eslint は--verboseオプションがなく、DEBUG=eslint:* yarn eslint
でログを出力する。
eslintrc自体のlinterがあればとよく思う。
prettierrc.json
{ "semi": true, "singleQuote": true, "trailingComma": "es5", "tabWidth": 4 }
自動セミコロン挿入の弊害を知ってから、セミコロンは入れている。
.prettierignore
build coverage .next .vscode public node_modules yarn.lock
jest.config.js
今回はじめて書いた。特徴は@swc-node/jestを使うことで、かなり高速化されていること。最近chakra-uiのtest環境がts-jestからこれになり、テストが1/4の時間で終わるようになった。、個人的には、ts-jest時代はWSL環境で動かすとOSが落ちる状態だったので、かなり助かっている。
Next.js + Jest のテスト環境を @swc/jest を使って高速化する を参考にして書いた部分が多い。uttkさんの記事は@swc/jest、この記事は@swc-node/jestで異なるライブラリを採用しているため注意が必要。tsc-nodeはtscの非公式版なのだが、最近next.jsにも採用されている期待株。
module.exports = { testEnvironment: 'jsdom', moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], modulePathIgnorePatterns: [ '<rootDir>/website/.cache', '<rootDir>/examples', '<rootDir>/tooling/cra-template*', ], transform: { '^.+\\.(ts|tsx)?$': [ '@swc-node/jest', { sourceMaps: true, // エラーを見やすくする( 有効じゃないと内容がズレて表示されます ) module: { type: 'commonjs', // 出力するファイルをcommonjsとする }, jsc: { parser: { syntax: 'typescript', // ソースコードをtypescriptとしてパースする tsx: true, // jsx記法を許可する }, transform: { react: { // 必須。省略すると "ReferenceError: React is not defined" が発生します runtime: 'automatic', }, }, }, }, ], }, testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/.next/'], transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$'], setupFilesAfterEnv: [ '@testing-library/jest-dom/extend-expect', '<rootDir>/jest.setup.ts', ], watchPlugins: [ 'jest-watch-typeahead/filename', 'jest-watch-typeahead/testname', ], collectCoverageFrom: [ 'pages/**/*.{js,ts,tsx}', 'components/**/*.{js,tsx,ts}', 'theme/**/*.{js,tsx,ts}', ], };
tsconfig.json
{ "compilerOptions": { "target": "es5", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, "forceConsistentCasingInFileNames": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "jsx": "react-jsx" }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules"] }
Next.jsのjsxはpreserve
になっているが、vscodeのauto-importができなくなる問題がある。そのため、開発中はjsxをreact-jsx
に変更している。つい10日前ほどにVsCodeに修正PRが出ていたのでいずれ改善されるだろう。
package.json > scripts
"scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint", "lint-v": "DEBUG=eslint:* next lint", "test": "jest --coverage", "test:watch": "jest --watch", },
テストのカバレッジ・ウォッチと、eslintのverboseを登録した。
ふりかえって
Next.js用の環境をつくるのをいい機会にLinter周辺の知識を学んだ。Next.jsのlinterやテストまわりの体験はかなり優れていたので、今後は積極的にNext.jsを使うだろうと思う。Vercelロックインの批判も多いが、的を射た批判はあまり多くないので、気にせず使っていきたい。
今後husky / lint-stagedを追加するかもしれない。