メモ。ここでいうaliasってのは@/hoge
とかでimportするやつ(Webpackの言う"alias")
↓とかあるけどcreate-react-app
で作成してreact-scripts
使う時は一工夫要る
qiita.com
TypeScript
何はともあれtsconfig.json
react-scripts
が起動するたびにこいつを書き変えてしまうので、extends
を使ってpathsを切り出す
tsconfig.json
{
"extends": "./tsconfig.paths.json"
}
tsconfig.paths.json
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": [
"src/*"
]
},
}
}
Webpack
react-scripts
の後ろにいるWebpackの設定をいじる方法がない
かといってejectはしたくないので、react-app-rewiredを使う
設定はconfig-overrides.js
に記述する
const path = require('path');
module.exports = function override(config) {
config.resolve = {
...config.resolve,
alias: {
'@': path.resolve(__dirname, 'src'),
},
};
return config;
};
ESLint
importまわりのLintをやってくれるeslint-plugin-importsというのがあるが、そのままではaliasをよしなにしてくれない
Webpackの設定を使ってくれるeslint-import-resolver-webpackがあるが、webpack.config.js
が必要となる
config-overrides.js
の内容をコピペしても良いが、うまいこと対応する方法があり、これをやると保守性が高くてよさそう
webpack.config.js
const { paths } = require('react-app-rewired');
const overrides = require('react-app-rewired/config-overrides');
const config = require(paths.scriptVersion + '/config/webpack.config.js');
module.exports = overrides.webpack(config, process.env.NODE_ENV);
TypeScriptプロジェクトの場合は.ts(x)ファイルもESLintに認識してもらう必要がある(1敗)が、eslint-import-resolver-typescriptを使うとその辺をよしなにしてくれるので使うと良い
.eslintrc.json
{
"extends": [
"plugin:import/errors",
"plugin:import/typescript"
],
"settings": {
"import/resolver": {
"webpack": {},
"typescript": {}
}
},
"plugins": [
"import"
]
}
メモ(諸々含めた自分用コピペテンプレート)
Prettier用の設定とかも入ってるので自分以外の人はよしなに
↓はreact-app-rewiredとESLint関係とPrettier関係(適宜更新する)
yarn add -D react-app-rewired @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint-config-prettier eslint-import-resolver-typescript eslint-import-resolver-webpack eslint-plugin-import eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-unused-imports prettier
eslintrc.json
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:import/errors",
"plugin:import/typescript",
"prettier"
],
"root": true,
"env": {
"node": true
},
"settings": {
"react": {
"version": "detect"
},
"import/resolver": {
"webpack": {},
"typescript": {}
}
},
"parser": "@typescript-eslint/parser",
"plugins": [
"react",
"react-hooks",
"@typescript-eslint",
"unused-imports",
"import"
],
"rules": {
"no-var": "error",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"sort-imports": "off",
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn",
{
"argsIgnorePattern": "^_"
}
],
"import/order": [
"error",
{
"alphabetize": {
"order": "asc"
}
}
]
},
"overrides": [
{
"files": [
"**/*.tsx",
"**/*.ts"
],
"rules": {
"react/prop-types": "off",
"react/display-name": "off",
"sort-imports": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-non-null-assertion": "warn"
}
}
]
}
.prettierrc
{
"singleQuote": true,
"jsxBracketSameLine": true
}
config-overrides.js
const path = require('path');
module.exports = function override(config) {
config.resolve = {
...config.resolve,
alias: {
'@': path.resolve(__dirname, 'src'),
},
};
return config;
};
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"baseUrl": "./",
"noFallthroughCasesInSwitch": true
},
"include": [
"src"
],
"exclude": [
"node_modules"
],
"extends": "./tsconfig.paths.json"
}
tsconfig.paths.json
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": [
"src/*"
]
},
}
}
webpack.config.js
const { paths } = require('react-app-rewired');
const overrides = require('react-app-rewired/config-overrides');
const config = require(paths.scriptVersion + '/config/webpack.config.js');
module.exports = overrides.webpack(config, process.env.NODE_ENV);