背景
私が React で作っている SPA で webpack, webpack-dev-server を下記のモジュールを使って HMR を有効にしていましたが、Functional Component がうまく更新されなかったりしてイマイチでした。せっかくなので最近 react が提供している react-refresh を使って、イケてる開発環境にしていきます。変更前の書き方がそもそも古いなどありそうですが、ご了承ください。
- @hot-loader/react-dom
- react-hot-loader
概要
react-hot-loader を削除し、react-refresh-webpack-plugin を導入します。
react-refresh-webpack-plugin の導入方法、react-hot-loader から来た人向けガイド に従って変更を行っていきます。
変更前
webpack.dev.js
module: {
rules: [
{
test: /\.(j|t)sx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
/* 中略 */
resolve: {
alias: {
"react-dom": "@hot-loader/react-dom",
index.tsx
import React from "react"
import ReactDOM from "react-dom"
function renderApp() {
ReactDOM.render(<App />, document.querySelector("#root"))
}
if (module.hot) {
module.hot.accept("components/App/App", () => {
renderApp()
})
}
App.tsx
import { hot } from "react-hot-loader/root"
import React from "react"
/* 中略 */
export default hot(App)
変更後
- @hot-loader/react-dom の alias を削除
- babel-loader の plugins に react-refresh/babel を追加
- plugins に ReactRefreshWebpackPlugin を追加
webpack.dev.js
const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin")
/* 中略 */
module: {
rules: [
{
test: /\.(j|t)sx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
plugins: [require.resolve("react-refresh/babel")],
},
/* 中略 */
plugins: [
new ReactRefreshWebpackPlugin()
- module.hot.accept() を削除
index.tsx
import React from "react"
import ReactDOM from "react-dom"
function renderApp() {
ReactDOM.render(<App />, document.querySelector("#root"))
}
renderApp()
- hot() を削除
App.tsx
import React from "react"
/* 中略 */
export default App
- .babelrc から react-hot-loader/babel を削除
.babelrc
- "react-hot-loader/babel",
あとがき
簡単でした。ちゃんと Functional Component もリロードせずに更新されていい感じです。