RailsからWebpackerを外してpureなwebpack構成にしてみる その2
前回、脱Webpackerすべくデフォルトの設定をいろいろ見て行ったが、今回はそれを参考に自分でwebpack.config.jsを作成し、Railsを繋ぎ込んでいこうと思う
Webpackerを除去する
とりあえずWebpackerと関連ファイルをきれいにしていく
- Gemfileとpackage.jsonからWebpackerを削除する
- ルートにある.browserslistrc、babel.config.js、postcss.config.jsの削除
- config/webpackディレクトリを中身ごと削除
- config/webpacker.ymlの削除
- bin/webpackとwebpack-dev-serverの削除
サンプルリポジトリでは↓の作業
https://github.com/hakozaru/remove_webpacker_sample/commit/943ec0c53edb50abd83b93dca76fd91dbb5f05f7
webpackを入れてビルド環境を作っていく
いろいろパッケージ入れたりして、とりあえずビルドが通るところまでやっていく
yarn add --dev webpack webpack-cli
でwebpackとcliツールを入れ、touch webpack.config.js
で設定ファイルを用意- 今回はES5にコンパイルできればOKでポリフィルは考えないという前提で進めることとし、トランスパイルはbabelではなくtscに任せる
yarn add --dev typescript
でTSを入れ、npx tsc --init
で設定ファイルを準備
- TSビルド時にエラーになるので型定義ファイルも入れておく
yarn add --dev @types/react @types/react-dom
- 必要なプラグインも入れておく =>
yarn add --dev case-sensitive-paths-webpack-plugin webpack-assets-manifest
ちなみにReactとReact DOMはwebpackerを入れた時に入っているので特にやることはない
ということでこの時点での各種設定ファイルは以下の通り
webpack.config.js
const path = require('path')
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin')
const WebpackAssetsManifest = require('webpack-assets-manifest')
module.exports = {
mode: process.env.NODE_ENV,
entry: {
application: path.resolve(__dirname, "./app/javascript/packs/application.js"),
},
output: {
filename: "js/[name]-[contenthash].js",
chunkFilename: "js/[name]-[contenthash].chunk.js",
hotUpdateChunkFilename: "js/[id]-[hash].hot-update.js",
path: path.resolve(__dirname, "./public/packs"),
publicPath: "/packs/",
},
resolve: {
extensions: ['.js', '.jsx', '.tsx'],
modules: [
path.resolve(__dirname, "./app/javascript"),
"node_modules"
]
},
module: {
strictExportPresence: true,
rules: [
{
test: /\.(ts|tsx)$/,
use: [
{
loader: "ts-loader"
},
],
},
],
},
plugins: [
new CaseSensitivePathsPlugin(),
new WebpackAssetsManifest({
entrypoints: true,
writeToDisk: true,
output: "manifest.json",
publicPath: true
}),
]
}
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"jsx": "react",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
}
}
これで webpack --progress --color --mode=development
してビルドが通るようになった
ビルド通るところまでやったコミット
yarnからビルドできるようにnpm scriptを用意する
↑で使った普通にビルドするためのものと、開発中に変更検出させるためのものの2つを用意する
"scripts": {
"dev": "webpack --progress --color --mode=development",
"watch": "webpack --progress --color --watch --mode=development"
}
ビルドしたJSをRailsから読み込めるようにする
Railsから使えるようにするためにはWebpackerが用意している javascript_pack_tag
のようなヘルパーが必要なんだけど、自分で用意してメンテしていくのは面倒なのでsimpacker gemに任せてしまおうと思う
Gemfileにsimpackerを入れて bin/rails simpacker:install
で設定ファイルなどをインストールすれば使えるようになる
simpackerはインストール時に最低限のwebpack.config.jsも生成してくれるので、そちらをベースにして必要な設定を追加していくという進め方でもいいかもしれない
const path = require("path");
const WebpackAssetsManifest = require("webpack-assets-manifest");
const { NODE_ENV } = process.env;
const isProd = NODE_ENV === "production";
module.exports = {
mode: isProd ? "production" : "development",
devtool: "source-map",
entry: {
application: path.resolve(__dirname, "app/javascript/application.js"),
},
output: {
path: path.resolve(__dirname, "public/packs"),
publicPath: "/packs/",
filename: isProd ? "[name]-[hash].js" : "[name].js",
},
resolve: {
extensions: [".js"],
},
plugins: [
new WebpackAssetsManifest({
publicPath: true,
output: "manifest.json",
}),
],
};
simpackerは javascript_pack_tag
を使えるようにしてくれるのでviewは特に変更しなくてもOK
あとはRailsを起動してwebpackをwatchモードで起動しておけば、webpack管理下のファイルの変更を感知して勝手にリビルドしてくれるようになる
ただし、現時点ではホットリロードには対応していないという致命的な欠点があるので、そこは別途やっていきたい
simpackerを入れたコミット↓ https://github.com/hakozaru/remove_webpacker_sample/commit/8377d357cfc95d8e00181ac5b93529e3d1e8f21b
ということで意外と簡単に脱Webpackerすることができた
改めてwebpack.config.jsを眺めると、これをWebpackerを通してあれこれやるのは確かに相当辛い
隠蔽が減ってシンプルに情報を得やすくなるのでとてもいい感じですね