Closed12

Next.js のプロジェクトセットアップ

FUJITA kazuya 🐠FUJITA kazuya 🐠

プロジェクトの前提
React: 18.x
ReactDOM: 18.x
Next.js: 12.x

導入するライブラリ等

  • CSSModules (Next.js にビルトイン)
  • TypeScript (4.8.2)
  • ESLint (8.23.0)
  • Prettier (2.7.1)
  • Storybook
  • jest
  • testing-library
  • msw
FUJITA kazuya 🐠FUJITA kazuya 🐠

絶対パス指定の設定

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": "preserve",
+  "baseUrl": ".",
+   "paths": {
+    "@/*": ["src/*"]
+   },
    "incremental": true
  },

https://nextjs.org/docs/advanced-features/module-path-aliases

FUJITA kazuya 🐠FUJITA kazuya 🐠

ESLint, Prettier の導入

インストール

yarn add -D eslint-config-airbnb @typescript-eslint/eslint-plugin eslint-plugin-unused-imports prettier eslint-config-prettier

設定ファイル

.eslintrc.js
/** @type {import('@typescript-eslint/experimental-utils').TSESLint.Linter.Config} */
const config = {
 extends: ['airbnb', 'plugin:@typescript-eslint/recommended', 'next/core-web-vitals', 'plugin:import/typescript', 'prettier'],
 rules: {
   'arrow-body-style': 'off',
   'no-restricted-syntax': [
     'error',
     {
       selector: 'TSEnumDeclaration',
       message: 'DO NOT DECLARE ENUM',
     },
   ],
   'import/order': [
     'error',
     {
       groups: ['builtin', 'external', 'internal', ['parent', 'sibling'], 'object', 'type', 'index'],
       'newlines-between': 'always',
       pathGroupsExcludedImportTypes: ['builtin'],
       alphabetize: { order: 'asc', caseInsensitive: true },
       pathGroups: [{ pattern: '**/**.css', group: 'index', position: 'before' }],
     },
   ],
   'react/jsx-filename-extension': [1, { extensions: ['.jsx', '.tsx'] }],
   'react/jsx-props-no-spreading': 'off',
   'react-hooks/rules-of-hooks': 'error',
   'react-hooks/exhaustive-deps': 'warn',
 },
};

module.exports = config;
.prettierrc.js
/** @type {import('prettier').Options} */
const config = {
  useWidth: 2,
  useTabs: false,
  semi: true,
  singleQuote: true,
  bracketSameLine: false,
  trailingComma: 'es5',
};

module.exports = config;

https://github.com/vercel/next.js/tree/e0cd06531bcd004fe73c1ab8836c28584c5c8286/packages/eslint-plugin-next

FUJITA kazuya 🐠FUJITA kazuya 🐠

stylelint の導入

インストール

yarn add -D stylelint stylelint-config-prettier stylelint-config-recess-order stylelint-config-standard stylelint-order

設定ファイルの追加

stylelint.config.js
/** @type {import('stylelint').Configuration} */
const config = {
  extends: ['stylelint-config-standard', 'stylelint-config-recess-order', 'stylelint-config-prettier'],
  plugins: ['stylelint-order'],
};

module.exports = config;
FUJITA kazuya 🐠FUJITA kazuya 🐠

npm scripts の追記

"scripts": {
   "dev": "next dev",
   "build": "next build",
   "start": "next start",
   "lint": "next lint",
+  "stylelint": "stylelint **/*.css",
+  "fix": "prettier --write src/ && next lint --fix && yarn stylelint --fix",
+  "typecheck": "tsc -p . --noEmit"
 },
FUJITA kazuya 🐠FUJITA kazuya 🐠

husky および lint-staged の追加

インストール

yarn add -D husky lint-staged

設定ファイル

.husky/pre-commit
  #!/bin/sh
  . "$(dirname "$0")/_/husky.sh"
 
- npm test
+ yarn lint-staged
package.json
 "scripts": {
   ...
-  "typecheck": "tsc -p . --noEmit"
+  "typecheck": "tsc -p . --noEmit",
+  "prepare": "husky install"
 },
...
+ "lint-staged": {
+   "*.{ts,tsx}": ["prettier --write", "eslint --fix", "bash -c tsc"],
+   "*.css": ["stylelint --fix"]
+ }

https://typicode.github.io/husky/#/

FUJITA kazuya 🐠FUJITA kazuya 🐠

テストライブラリの追加

インストール

yarn add -D jest ts-jest @types/jest eslint-plugin-jest eslint-plugin-jest-dom @testing-library/jest-dom @testing-library/react @testing-library/react-hooks @testing-library/user-event @types/testing-library__jest-dom

設定ファイル(ほぼ公式に記載のママ)
moduleNameMapper は実際のディレクトリ構成にあわせて修正する

jest.config.js
const nextJest = require('next/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: './',
});

/** @type {import(‘@jest/types’).Config.InitialOptions} */
const customJestConfig = {
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  testEnvironment: 'jsdom',
  moduleNameMapper: {
    // Handle module aliases (this will be automatically configured for you soon)
    '^@/(.*)$': '<rootDir>/src/$1',
  },
};

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig);
jest.setup.js
// Optional: configure or set up a testing framework before each test.
// If you delete this file, remove `setupFilesAfterEnv` from `jest.config.js`

// Used for __tests__/testing-library.js
// Learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom/extend-expect'
tsconfig.jest.json
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "jsx": "react"
  }
}

https://nextjs.org/docs/advanced-features/compiler#jest

ESLint の設定追記

.eslintrc.js
  extends: [
    'plugin:react/recommended',
    'airbnb',
    'plugin:@typescript-eslint/recommended',
    'plugin:import/typescript',
    'plugin:storybook/recommended',
+   'plugin:jest/recommended',
+   'plugin:jest-dom/recommended',
    'prettier',
  ],
...
-  plugins: ['react', '@typescript-eslint', 'react-hooks'],
+  plugins: ['react', '@typescript-eslint', 'react-hooks', 'jest', 'jest-dom'],
FUJITA kazuya 🐠FUJITA kazuya 🐠

Storybook の追加

インストール

npx sb init

Storybook の ESLint プラグイン(eslint-plugin-storybook)をインストールするかどうかを聞かれるのでインストールしておく。

Interactions の設定

https://storybook.js.org/docs/react/essentials/interactions

関連ライブラリを追加

# storybook を testing-library でテストするためのアドオン
yarn add -D @storybook/testing-react


# CSF3.0 の play 関数等を利用するためのアドオン
yarn add -D @storybook/testing-library
このスクラップは2023/04/08にクローズされました