2021年3月11日 • ☕️ 4 min read

フロントエンドプロジェクトでもどんどん複雑になりつつ、深いフォルダの構成が当たり前のことになってきました。例えばcreate-react-appを利用する場合、下記のようなフォルダ構成が普通でしょう。

src
 - components
 - hooks
 - lib
 - store
 - views

さらに、components、またviewsフォルダの中に、各コンポーネントを独立なフォルダに分けて置くこともよくあります。

src
 - views
   - MenuView
     - MenuView.tsx
     - MenuView.style.tsx (styled-components)
     - MenuView.test.tsx
     - index.ts

となると、MenuView.tsxから、Reduxのストアをimportするとき、たくさん相対パスが現れます。

import { setActiveMenu } from "../../store/menu/actions";

もちろん、階層が変わると、../も増えるでしょう。これからは絶対パスの登場タイムだ。

方法はいくつかがありますが、今日はbabelで実現しましょう。

create-react-appのための設定

tsconfig.jsonの設定

一般的なTypeScriptプロジェクトでは下記のものをtsconfig.jsoncompilerOptionsに書き込めばいいんですが、create-react-appの場合はちょっと違います。react-scriptsで起動するとき、tsconfig.jsonの一部分がデフォルトのものに上書きされる可能性があります。

"baseUrl": "./",
"paths": {
  "components/*": ["./src/components/*"],
  "store/*": ["./src/store/*"],
  "views/*": ["./src/views/*"],
}

なので、新しいファイルを作って、tsconfig.jsonにincludeしなければいけません。

tsconfig.paths.json
{
  "compilerOptions": {
    "baseUrl": "./",
    "paths": {
      "components/*": ["./src/components/*"],
      "store/*": ["./src/store/*"],
      "views/*": ["./src/views/*"],
    }
  }
}

そして、tsconfig.jsonの中

tsconfig.json
{
  "extends": "./tsconfig.paths.json",
}

これで、VSCodeに絶対パスでimportしてもlintエラーに怒られないでしょう。

babelの設定

TypeScriptの設定をカスタマイズと同じように、create-react-appを使うと、babelをカスタマイズしたいとき、ちょっと工夫する必要があります。

では、まずは何でbabelを選ぶの?

Why babel?

  1. 個人にとってWebpackの記述よりさらにわかりやすい
  2. Tree-shakingのライブラリいくつがあって、さまざまなライブラリのTree-shakingを対応しやすい

    fontawesomeramdaみたいに一般的なフォルダ構成を採用していないライブラリであれば、babel-plugin-transform-importsの存在はとても助かります。

create-react-app with babel

一番簡単な方法はcustomize-crareact-app-rewiredを利用することとなります。

  1. パッケージをインストール
npm install --save-dev react-app-rewired customize-cra 

# yarnの場合
yarn add -D react-app-rewired customize-cra 
  1. そして、プロジェクトのルートフォルダにconfig-overrides.jsを作成
config-overrides.js
const { useBabelRc, override } = require("customize-cra");

module.exports = override(useBabelRc());
  1. package.jsonのスクリプトの対応

startなどのスクリプトをreact-scriptsからreact-app-rewiredへ変えます。

package.json
--- a/package.json
+++ b/package.json
@@ -5,9 +5,9 @@
   "scripts": {
     "type-check": "tsc --pretty --noEmit --project ./tsconfig.json",
     "lint": "eslint ./src --ext ts --ext tsx --ext js",
-    "start": "react-scripts start",
-    "build": "react-scripts build",
-    "test": "react-scripts test",
+    "start": "react-app-rewired start",
+    "build": "react-app-rewired build",
+    "test": "react-app-rewired test",
     "eject": "react-scripts eject"
   },
   "dependencies": {
@@ -50,7 +50,7 @@
  1. ルートフォルダに.babelrcファイルにbabel設定を記入

※要注意:残念ですが、babel.config.jsだと認識されない(2021.03.11時点)

これで、babelを使えるようになりました。

babelの設定

  1. babelプラグインの導入
npm install --save-dev babel-plugin-module-resolver
  1. .babelrcの編集
.babelrc
{
  "plugins": [
    [
      "module-resolver",
      {
        "root": ["./"],
        "alias": {
          "components": "./src/components",
          "views": "./src/views",
          "store": "./src/store"
        }
      }
    ]
  ]
}

完了

これから絶対パスでimportしても問題ありません。VSCodeでもちゃんとヒント出してくれます。

import { setActiveMenu } from "store/menu/actions";

意外に面倒ですね。next.jsに慣れた自分にとって、next.jsのほうがカスタマイズしやすそうな気がします。


関連投稿

コストコオンラインの商品価格変動チェックのバッチを作ってみた

2021年3月23日

ThunderMiracle

Blog part of ThunderMiracle.com