🌀

Webpack 4でWDS(webpack-dev-server)のリロードが効かないときの対処法

2022/12/03に公開

前提

「Reactを勉強しながら自分用の便利ツール、作りたいなあ」とおもったこと、皆さんもあると思います。
そんなときにこの記事を見つけてしまいました。
https://qiita.com/faunsu/items/b5ad8295cc129c314dcd
ここには私がやろうとしていたこと(GASでデプロイで来て、デザインはMUIとかで楽したい)がだいたいできそうでした。

ただこのコードはちょっと作りが甘く、数か所詰まりました。
具体的にはホットリロードです。

現代開発ではホットリロードは欠かせないと思いますが、そのホットリロードが効かないという重大な問題。
コンソールを見るとこんなふうになっていました。

この赤文字のところは関係ありません。問題はこれです。

有効になっているのに、ソースを変更して保存してもいつまでもリロードされない。これはおかしい。

環境

ソフトウェア

  • Vivaldiブラウザ
  • VSCode
  • yarn

ライブラリ

package.json
{
  "dependencies": {
    "@emotion/react": "^11.9.3",
    "@emotion/styled": "^11.9.3",
    "@mui/icons-material": "^5.8.4",
    "@mui/material": "^5.8.7",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "recoil": "^0.7.4",
    "typescript": "4.4.4"
  },
  "devDependencies": {
    "@google/clasp": "^2.4.1",
    "@types/google-apps-script": "^1.0.49",
    "@types/node": "^16.7.13",
    "@types/react": "^18.0.0",
    "@types/react-dom": "^18.0.0",
    "@types/webpack": "^5.28.0",
    "html-webpack-inline-source-plugin": "1.0.0-beta.2",
    "html-webpack-plugin": "4.2.0",
    "ts-loader": "6.2.2",
    "webpack": "4.42.1",
    "webpack-cli": "3.3.11",
    "webpack-dev-server": "3.10.3"
  }
}

結論

webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin');
const path = require('path');

/** @type {import('webpack').Configuration} */
const config = {
-   mode: 'production',
+   mode: 'development',
  target: 'web',
  entry: path.resolve('src', 'index.tsx'),
  output: {
    path: path.resolve('server', 'hosting'),
+    publicPath: '/js/',
    filename: 'main.js',
  },
  module: {
    rules: [{ test: /\.tsx?$/, use: 'ts-loader' }],
  },
  resolve: { extensions: ['.ts', '.tsx', '.js', '.json'] },
  plugins: [
    new HtmlWebpackPlugin({ inject: true, inlineSource: '.(js|css)$', template: path.resolve('public', 'index.html') }),
    new HtmlWebpackInlineSourcePlugin(HtmlWebpackPlugin),
  ],
+  devServer: {
+    publicPath: "/",
+    contentBase: "./public",
+    hot: true
+  },
};

module.exports = config;

この3箇所を書き換えたら改善しました。
15件ぐらいサイトをはしごして解決しました。

解説

mode: 'production'

普通に考えてテスト環境なので'production'じゃなくて'development'で問題ないんじゃないかな…と思ったので書き換えました。
多分改善には貢献していません。

publicPath: '/js/'

「publicPath: '/js/' っていれたらええんやで」という記事を複数見かけたので実践しましたが、こうなりました。

※引用元 https://stackoverflow.com/questions/33382526/webpack-dev-server-serves-a-directory-list-instead-of-the-app-page?newreg=9a9188bcb10f405eb4e086b6573efc0b

これだと先に進めません。ホットリロードどころか意味の分からない物が出てきました。

今webpackに付いてのガイドを探していたらこんなものが出てきました。
https://qiita.com/riversun/items/d27f6d3ab7aaa119deab
このコードは何かというと、ビルドされたバンドルjsにブラウザからアクセスできるらしいです。これいる?

devServer

これを追加したら解決しました。
Q&Aについてたドキュメントを読んでみたのですが、なんのことやらさっぱり。
どうやらhot: trueのおかげで読み込めてるっぽいことだけは理解できました。その他のオプションがなんのために有るのかはわかりません。すみません。

ところで、hot: truehot: 'only'にするとページ全体のリロードじゃなくてうまいこと反映されると公式ガイドに書いてあったのですが、Boolean入れろ!ってエラーが出て終わりました。なんやねん。

教訓

documentation原文を参照して問題なく解決できるようになりたいです。英語が読めたってdocumentationが読めなきゃ意味ないんですよね。
ところで、このソースコードを配布した人はデバッグをちゃんとしたのだろうか…一箇所「import React from 'react'」が「import Raect from 'raect'」になってましたけど…
でもテンプレートは概ねしっかり動いているので感謝の気持ちで使います。

おまけ

初心者すぎてgit cloneですでに躓きました。

git clone https://github.com/ymuichiro/react-gas-boilerplate.git
yarn install

と書いてありますが、実際はyarn installをする前にcdしてclone先にいかないと意味がありません(謎エラーが頻発します)。
ここに書いたってしょうがないかもしれませんが、私と同じく超初心者の方はご参考までに。

それとClaspなるものも恥ずかしながら今回初めて知りました。ローカルのプロジェクトをbundleしたコードをなんやかんやしてそのままGASプロジェクトにアップロードできるらしいです。わあ便利。コードエディタのちまちま作業から開放されます。
https://coxcox.hatenablog.com/entry/2019/04/05/222532
なお、アップロードするとターゲットのプロジェクトにもともとあったスクリプトは跡形もなく消滅するので気をつけてください。私は謎の勘が働いて、deploy前にコピペでバックアップを取っていたので事なきを得ました。

参考文献

https://stackoverflow.com/questions/33382526/webpack-dev-server-serves-a-directory-list-instead-of-the-app-page?newreg=9a9188bcb10f405eb4e086b6573efc0b
https://webpack.js.org/configuration/dev-server/
https://webpack.js.org/configuration/dev-server/#devserver

Discussion