タイトル長くてすみません。
ひと昔前までは、react-create-appで作成したプロジェクトの webpack.config を上書きするには、eject
するしか方法がなかったのですが、現在は react-app-rewiredを使うことで上書きが可能です。
この方法を使った場合、react-create-app が提供するツールの動作保証対象外となります。つまり、これ以降発生した問題は自己責任で解決しなければなりません。ご注意ください。
紹介する内容は、こちらの Github で見ることができます。
react-app-rewired を導入する
基本的にはリポジトリにある README.md の通りに導入します。より具体的な例については後で少し紹介します。
react-app-rewired をインストールする
まず npm モジュールをインストールします。
npm install react-app-rewired --save-dev
プロジェクトのルートディレクトリにconfig-overrides.js
を作成する
プロジェクトのルートディレクトリにconfig-overrides.js
を作成します。とりあえず、ファイルの中身は公式ドキュメントのままにしておきますが、詳しくは後で紹介します。
module.exports = function override(config, env) {
//do stuff with the webpack config...
return config;
};
package.json
のsctipts
を変更する
package.json
を変更します。
基本的にはreact-scripts
の部分をreact-app-rewired
に変更すればいいのですが、TypeScript プロジェクトの場合は--scripts-version
に起動スクリプトの名前が必要です。これは、react-app-rewired の内部で TypeScript 用の起動スクリプトにスイッチするために利用しています。
"scripts": {
- "start": "react-scripts start",
+ "start": "react-app-rewired start --scripts-version react-scripts-ts",
- "build": "react-scripts build",
+ "build": "react-app-rewired build --scripts-version react-scripts-ts",
- "test": "react-scripts test --env=jsdom",
+ "test": "react-app-rewired test --env=jsdom --scripts-version react-scripts-ts",
},
動作確認する
最後にプロジェクトの開発用サーバーの起動とビルドの確認をします。
# 開発用サーバーの起動
npm start
# ビルド
npm build
正しく動いているようであれば、ひとまず導入は完了です。
config-overrides.js
をカスタマイズする
上の内容では元の Webconfig のままなのでカスタマイズする必要がありますが、その内容は中〜上級者向けです。カスタマイズのプロセスは次の通りです。
- ここからconfig-overrides.js のテンプレートを取得する
- 設定変更用の関数(慣例で
rewire(再結線する)
と呼ぶことが多い)を作成する - rewire 関数を config-overrides.js に追加する
config-overrides.js
のテンプレートは大まかに次のようなファイルになっています。
いくつかカスタマイズできるポイントがあるのですが、webpack.config のカスタマイズだけであれば、webpack
の部分だけ注視していればいいと思います。
module.exports = {
// 開発サーバーのカスタマイズポイント
devServer: function (configFunction) {
return function (proxy, allowedHost) {
// デフォルト設定の開発サーバーを作成する
const config = configFunction(proxy, allowedHost);
// この辺でカスタマイズする
return config;
};
},
// `npm test`のカスタマイズポイント
jest: function (config) {
// この辺でカスタマイズする
return config;
},
// webpack.configのカスタマイズポイント
webpack: function (config, env) {
// この辺でカスタマイズする
return config;
},
};
(実践例)Sass 設定のカスタマイズ
では、既存の webpack.config の Sass 設定をカスタマイズしてsass-loader
を追加してみましょう。
react-create-app
の公式では別の方法が推奨されていますが、自分はこの昔ながらのやり方が好きなのです。
まず、Sass 設定を上書きするrewireSass
関数を作成します。
// config-overrides.js
const rewired = require("react-app-rewired");
function rewireSass(config) {
const cssLoader = rewired.getLoader(
config.module.rules,
// ここでloaderをフィルタする
(rule) => rule.test && String(rule.test) === String(/\.css$/)
);
// 新しいsass-loaderの設定
const sassLoader = {
test: /\.scss$/,
use: [...(cssLoader.loader || cssLoader.use), "sass-loader"],
};
// sass-loaderを追加する
const oneOf = config.module.rules.find((rule) => rule.oneOf).oneOf;
oneOf.unshift(sassLoader);
return config;
}
react-app-rewired
のパッケージにgetLoader
という loader を pick up する関数があるので、これを使って既存の config から上書きするターゲットの loader だけを抽出します。
あとは、コードを見てもらうとわかると思うのですが、普通の JavaScript プログラミングです。
途中、console.log
などを出しながら途中経過を見てカスタマイズしていきます。
なので、将来 react-create-app 側の wepack.config が変わったり、Webpack 自体のバージョンが上がった場合は、容易に動作しなくなると思います。
このrewireSass
関数をconfig-overrides.js
に追加します。
// config-overrides.js
function rewireSass(config) {
...
}
module.exports = {
// 開発サーバーのカスタマイズポイント
devServer: function (configFunction) {
return function (proxy, allowedHost) {
// デフォルト設定の開発サーバーを作成する
const config = configFunction(proxy, allowedHost);
// この辺でカスタマイズする
return config;
}
},
// `npm test`のカスタマイズポイント
jest: function (config) {
// この辺でカスタマイズする
return config;
},
// webpack.configのカスタマイズポイント
webpack: function (config, env) {
// この辺でカスタマイズする
config = rewireSass(config, env); // <--------- ここに追加
return config;
},
};
Sass ファイルが Webpack で変換されていれば、無事 OK です。
まとめ
react-create-app の Webpack.config をカスタマイズする方法でした。
react-create-app 便利なのですが、いままで作ったプロダクトではカスタマイズしなかったことなかったなぁ。。。 ちなみにカスタマイズは「自己責任」です。
カスタマイズする人は、「なぜ最近の Web フロントエンドはこんなに難しくなったのか。。。」と血の涙を流しながらやるといいでしょう。