Vite +TypeScript + React + Eslint(airbnb) + Prettier + Stylelint + Emotion + Storybook の開発環境構築
構築環境
- windows10 WSL2 Ubuntu-20.04
- node 16.13.0
- npm 8.1.0
- Vscode
機能
- Vite
- typescript
- lint + format
- Eslint
- airbnb
- Prettiter
- Stylelint
- Eslint
- storybook
リポジトリ
Vite app
npm init vite@latest
react-ts
を選択
.editorconfigを追加
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
Eslintの導入|パッケージのインストール
npm i -D eslint
npx eslint --init
対話式で選択
npx eslint --init
✔ How would you like to use ESLint? · style
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · react
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser, node
✔ How would you like to define a style for your project? · guide
✔ Which style guide do you want to follow? · airbnb
✔ What format do you want your config file to be in? · JavaScript
Checking peerDependencies of eslint-config-airbnb@latest
The config that you've selected requires the following dependencies:
eslint-plugin-react@^7.27.1 @typescript-eslint/eslint-plugin@latest eslint-config-airbnb@latest eslint@^7.32.0 || ^8.2.0 eslint-plugin-import@^2.25.3 eslint-plugin-jsx-a11y@^6.5.1 eslint-plugin-react-hooks@^4.3.0 @typescript-eslint/parser@latest
✔ Would you like to install them now with npm? · No / Yes
Installing eslint-plugin-react@^7.27.1, @typescript-eslint/eslint-plugin@latest, eslint-config-airbnb@latest, eslint@^7.32.0 || ^8.2.0, eslint-plugin-import@^2.25.3, eslint-plugin-jsx-a11y@^6.5.1, eslint-plugin-react-hooks@^4.3.0, @typescript-eslint/parser@latest
AirbnbのESLintコンフィグをTypeScriptに対応させて強化する
npm i -D eslint-config-airbnb-typescript
Eslintの導入|設定
自動生成された .eslintrc.js
に以下を追加
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
'airbnb',
+ 'airbnb-typescript',
+ 'airbnb/hooks',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:@typescript-eslint/recommended-requiring-type-checking',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 13,
sourceType: 'module',
project: './tsconfig.json'
},
plugins: [
'react',
'@typescript-eslint',
],
rules: {
},
};
Eslintの導入|動作検証
npx eslint . --ext .js,.jsx,.ts,.tsx
0:0 error Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: .eslintrc.js.
The file must be included in at least one of the projects provided
0:0 error Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: vite.config.ts.
The file must be included in at least one of the projects provided
Eslintの導入|設定
Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser. の解消
tsconfig.json
に 以下を追加
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": [
"DOM",
"DOM.Iterable",
"ESNext"
],
"allowJs": false,
"skipLibCheck": false,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"./src",
"./.eslintrc.js",
"./vite.config.ts"
]
}
Eslintの導入|動作検証
npx eslint . --ext .js,.jsx,.ts,.tsx
以下のeslint errorがでるようになる
21:31 error Missing trailing comma @typescript-eslint/comma-dangle
1:1 error 'vite' should be listed in the project's dependencies, not devDependencies import/no-extraneous-dependencies
1:36 error Missing semicolon @typescript-eslint/semi
2:1 error '@vitejs/plugin-react' should be listed in the project's dependencies, not devDependencies import/no-extraneous-dependencies
2:41 error Missing semicolon @typescript-eslint/semi
6:21 error Missing trailing comma @typescript-eslint/comma-dangle
7:3 error Missing semicolon @typescript-eslint/semi
Eslintの導入|npm scriptsの追加
{
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"serve": "vite preview",
+ "lint:eslint": "eslint --ignore-path .gitignore . --ext .js,.jsx,.ts,.tsx",
+ "fix:eslint": "eslint --fix --ignore-path .gitignore . --ext .js,.jsx,.ts,.tsx"
},
}
Eslintの導入|ルールのカスタマイズ
react/react-in-jsx-scopeをoffにする
React v17からは以下のインポートが不要になったため
import React from "react";
ルールの追加
rules: {
'react/react-in-jsx-scope': 'off',
},
コンポーネントはアロー関数で書く様に、ルールの追加
rules: {
'react/function-component-definition': [
'error',
{
namedComponents: 'arrow-function', // 'function-declaration' | 'function-expression' | 'arrow-function'
},
],
},
vite.config.ts
の以下のエラーをoffにする
1:1 error 'vite' should be listed in the project's dependencies, not devDependencies import/no-extraneous-dependencies
2:1 error '@vitejs/plugin-react' should be listed in the project's dependencies, not devDependencies import/no-extraneous-dependencies
ルールの追加
+ overrides: [
+ {
+ files: ['**/vite.config.ts'],
+ rules: {
+ 'import/no-extraneous-dependencies': 'off',
・・・省略
+ },
+ },
+ ],
Eslintの導入|Eslintのerror修正
自動修正
npm run fix:eslint
手動修正
エラー内容
14:58 error 'count' is already declared in the upper scope @typescript-eslint/no-shadow
-<button type="button" onClick={() => setCount((count) => count + 1)}>
+<button type="button" onClick={() => setCount(count + 1)}>
Eslintの導入|import/order rules setting
importの順番ルールを追加
公式を参考に独自ルールを追加
plugins: [
'react',
'@typescript-eslint',
+ 'import',
],
overrides: [
{
files: ['**/vite.config.js'],
rules: {
'import/no-extraneous-dependencies': 'off',
},
},
+ {
+ // import/order rules setting
+ files: ['src/**/*.{js,jsx,ts,tsx}'],
+ rules: {
+ 'import/order': [
+ 'error',
+ {
+ groups: [
+ 'builtin',
+ 'external',
+ 'parent',
+ 'sibling',
+ 'index',
+ 'object',
+ 'type',
+ ],
+ alphabetize: {
+ order: 'asc',
+ },
+ 'newlines-between': 'always',
+ },
+ ],
+ },
+ },
],
Eslintの導入|eslint-plugin-unused-imports
未使用のインポートを検知できるように
パッケージのインストール
npm i -D eslint-plugin-unused-imports
公式通りにルール追加
plugins: [
'react',
'@typescript-eslint',
'import',
+ 'unused-imports',
],
rules: {
'react/react-in-jsx-scope': 'off',
'react/function-component-definition': [
'error',
{
namedComponents: 'arrow-function', // 'function-declaration' | 'function-expression' | 'arrow-function'
},
],
+ '@typescript-eslint/no-unused-vars': 'off',
+ 'unused-imports/no-unused-imports': 'error',
+ 'unused-imports/no-unused-vars': [
+ 'warn',
+ {
+ vars: 'all',
+ varsIgnorePattern: '^_',
+ args: 'after-used',
+ argsIgnorePattern: '^_',
+ },
+ ],
},
Emotionの導入|css-in-js
必要パッケージをインストール
npm i @emotion/react
npm i -D @emotion/babel-plugin
Emotionの導入|Babelの設定
vite.config.js にBabelの設定を追加
- plugins: [react()],
+ plugins: [
+ react({
+ jsxImportSource: '@emotion/react',
+ babel: {
+ plugins: ['@emotion/babel-plugin'],
+ },
+ }),
+ ],
Emotionの導入|DEMOコード
DEMOコード
import { css } from '@emotion/react';
const style = css`
& {
color: #333;
}
p {
font-size: 14px;
}
&.large p {
font-size: 28px;
}
@media (min-width: 1024px) {
p {
font-size: 28px;
color: #aaa;
transition: opacity 0.3s ease-out;
}
p:hover {
opacity: 0.5;
}
&.large p {
font-size: 56px;
}
}
`;
type Props = {
large: boolean;
};
const Demo: React.VFC<Props> = ({ large }: Props) => (
<div className={`demo ${large ? 'large' : ''}`.trim()} css={style}>
<p>Demo</p>
</div>
);
export default Demo;
Emotionの導入|VSCodeの設定
拡張機能のインストール
tsxでemmet(css)が実行できるようになる
追記:上記リンク切れになっていたので
エディタ上でcss propsの警告がでないように
{
"compilerOptions": {
・・・省略
"jsxImportSource": "@emotion/react"
}
}
Stylelintの導入|パッケージのインストール
npm i -D stylelint stylelint-config-recess-order stylelint-config-standard postcss-syntax @stylelint/postcss-css-in-js
Stylelintの導入|ルール設定
.stylelintrcを作成して以下を追加
.stylelintrc記述内容
{
"extends": [
"stylelint-config-standard",
"stylelint-config-recess-order"
],
"rules": {},
"overrides": [
{
"files": [
"**/*.jsx",
"**/*.tsx"
],
"rules": {
},
"customSyntax": "@stylelint/postcss-css-in-js"
}
]
}
Stylelintの導入|npm scriptsを追加
"lint:stylelint": "stylelint ./src/**/*.{css,jsx,tsx}",
"fix:stylelint": "stylelint --fix ./src/**/*.{css,jsx,tsx}"
Stylelintの導入|vscodeの設定
エディタ上でもstylelintが実行できるように
setteing.json記述内容
{
"editor.codeActionsOnSave": {
"source.fixAll.stylelint": true
},
"css.validate": false,
"stylelint.validate": ["css", "postcss", "javascriptreact", "typescriptreact"]
}
Stylelintの導入|errorの修正
fix:stylelint
手動修正
Prettierの導入|インストール
npm i -D prettier eslint-config-prettier stylelint-config-prettier
Prettierの導入|ルールの追加
{
"singleQuote": true,
"trailingComma": "all"
}
Prettierの導入|npm scriptsの追加
"format:check": "prettier --check --ignore-path .gitignore './**/*.{js,jsx,ts,tsx,json,css}'",
"format:fix": "prettier --write --ignore-path .gitignore './**/*.{js,jsx,ts,tsx,json,css}'"
Prettierの導入|競合ルールの無効化
extends: [
・・・省略
'prettier',
],
・・・省略
"extends": [
・・・省略
"stylelint-config-prettier"
],
VSCodeの設定|ファイル保存の自動フォーマット
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.formatOnPaste": false,
"editor.formatOnType": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.fixAll.stylelint": true
},
"css.validate": false,
"stylelint.validate": ["css", "javascriptreact", "typescriptreact"]
}
VSCodeの設定|推奨拡張機能
{
"recommendations": [
"editorconfig.editorconfig",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"stylelint.vscode-stylelint",
"jpoissonnier.vscode-styled-components"
]
}
Storybookの導入|Install Storybook
npx sb init
Storybookの導入|storybookのeslintの導入
npx sb@next automigrate
eslintのルールをoff
overrides: [
///省略
{
files: ['**/*.stories.*'],
rules: {
'react/jsx-props-no-spreading': 'off',
},
},
],
Storybookの導入|storybookのbabel設定を追加
この設定をしないとemotionがエラーで動作しない
{
"presets": [
[
"@babel/preset-react",
{ "runtime": "automatic", "importSource": "@emotion/react" }
]
],
"plugins": ["@emotion/babel-plugin"]
}
追記:上記だと Introduction.stories.mdx(storybook)が表示されなくなるので下記のように設定変更が必要
Introduction.stories.mdx が不要の場合は上記でいける
参照
公式では@emotion/babel-plugin
を推奨しているが・・
-
storybook/.babelrc を削除
-
.storybook/main.js にbabelの設定を追加
babel: async (options) => ({
...options,
presets: [...options.presets, '@emotion/babel-preset-css-prop'],
}),
最終確認
開発環境するか
npm run dev
ビルドできるか
npm run build
おっとこけたw
s an 'any' type.
Try `npm i --save-dev @types/babel__core` if it exists or add a new declaration (.d.ts) file containing `declare module '@babel/core';`
1 import type { ParserOptions } from '@babel/core';
s an 'any' type.
Try `npm i --save-dev @types/babel__core` if it exists or add a new declaration (.d.ts) file containing `declare module '@babel/core';`
3 import type { TransformOptions } from '@babel/core';
以下の型定義がいるらしい
npm i --save-dev @types/babel__core
再ビルド!!今度は成功
ビルドしたものがプレビューできるか
npm run serve
OK!
## GitHubへPUSH!!
StoryBookが起動しないことに気づいたので修正w
emmotionのcss propsが影響
Storybookを動く様にw