react-hot-loader 和 webpack-dev-server 不会重新加载更改
Posted
技术标签:
【中文标题】react-hot-loader 和 webpack-dev-server 不会重新加载更改【英文标题】:react-hot-loader and webpack-dev-server don't reload changes 【发布时间】:2018-12-03 19:00:13 【问题描述】:我尝试关注 react-hot-loader/getstarted 在我的 webpack 配置中启动并运行 react-hot-loader。当我对组件进行一些更改时,react-hot-loader 不会重新加载更改。我更新了 npm 脚本,将 react-hot-loader 添加到 babel 和 webpack 配置中,并将 module.hot.accept
添加到 index.jsx
中。
package.json
"scripts":
"dev": "webpack-dev-server -d --progress --colors --port 8090 --hot --inline",
,
"dependencies":
"aphrodite": "^2.2.1",
"bootstrap": "^4.1.1",
"bootstrap-select": "^1.13.1",
"classnames": "^2.2.5",
"d3": "^3.5.17",
"fixed-data-table-2": "^0.8.13",
"font-awesome": "^4.7.0",
"jquery": "^3.3.1",
"js-cookie": "^2.2.0",
"lodash": "^4.17.10",
"moment": "^2.22.1",
"popper.js": "^1.14.3",
"react": "^16.3.2",
"react-bootstrap-typeahead": "^3.1.3",
"react-datetime": "^2.14.0",
"react-dom": "^16.3.2",
"react-hot-loader": "^4.3.3",
"react-loadable": "^5.4.0",
"react-modal": "^3.4.4",
"react-redux": "^5.0.7",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"react-router-redux": "^5.0.0-alpha.9",
"react-slidedown": "^1.3.0",
"react-tippy": "^1.2.2",
"react-toastify": "^4.0.1",
"react-transition-group": "^2.3.1",
"redux": "^4.0.0",
"redux-saga": "^0.16.0"
,
"devDependencies":
"autoprefixer": "^8.4.1",
"babel": "^6.23.0",
"babel-core": "^6.26.3",
"babel-eslint": "^8.2.3",
"babel-loader": "^7.1.4",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-transform-async-to-generator": "^6.24.1",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.1",
"babel-preset-latest": "^6.24.1",
"babel-preset-react": "^6.24.1",
"css-loader": "^0.28.11",
"eslint": "^4.19.1",
"eslint-config-airbnb": "^16.1.0",
"eslint-plugin-import": "^2.11.0",
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-react": "^7.7.0",
"file-loader": "^1.1.11",
"http-server": "^0.11.1",
"less": "^3.0.2",
"less-loader": "^4.1.0",
"node-sass": "^4.9.0",
"npm-install-webpack-plugin": "^4.0.5",
"postcss": "^6.0.22",
"postcss-loader": "^2.1.4",
"redux-devtools-extension": "^2.13.2",
"sass-loader": "^7.0.1",
"sass-resources-loader": "^1.3.3",
"style-loader": "^0.21.0",
"url-loader": "^1.0.1",
"webpack": "^4.6.0",
"webpack-cli": "^2.1.2",
"webpack-dev-server": "^3.1.4",
"webpack-merge": "^4.1.2",
"webpack-notifier": "^1.6.0"
.babelrc
"presets": [
[
"latest",
"es2015":
"modules": false
],
"react"
],
"plugins": [
"transform-object-rest-spread",
"transform-class-properties",
"syntax-dynamic-import",
"transform-async-to-generator",
"react-hot-loader/babel"
]
webpack.config.js
const webpack = require('webpack');
const webpackMerge = require('webpack-merge');
const path = require('path');
const WebpackNotifierPlugin = require('webpack-notifier');
const TARGET = process.env.npm_lifecycle_event;
console.log(`target event is $TARGET`);
let outputFileName = 'app';
outputFileName += TARGET === 'prod' ? '.min.js' : '.js';
const common =
entry: ['babel-polyfill', 'react-hot-loader/patch', './index.jsx'],
output:
publicPath: '/',
,
module:
rules: [
test: /\.js[x]?$/,
exclude: /(node_modules)/,
use:
loader: 'babel-loader',
,
,
],
,
plugins: [
new webpack.ProvidePlugin(
jQuery: 'jquery',
$: 'jquery',
jquery: 'jquery',
'window.jQuery': 'jquery',
),
new WebpackNotifierPlugin(),
],
resolve:
modules: [
path.resolve('.'),
path.resolve('script'),
path.resolve('script', 'views'),
'node_modules',
],
extensions: ['.js', '.jsx', '.json'],
,
;
if (TARGET === 'dev' || !TARGET)
module.exports = webpackMerge(common,
devtool: 'eval-source-map',
output:
filename: 'bundle.js',
sourceMapFilename: '[file].map',
,
module:
rules: [
test: /\.scss$/,
loaders: [
'style-loader',
'css-loader',
loader: 'postcss-loader',
options:
config:
path: 'postcss.config.js',
,
,
,
'sass-loader',
],
,
test: /\.less$/,
loaders: ['style-loader', 'css-loader', 'less-loader'],
,
test: /\.css$/,
use: ['style-loader', 'css-loader'],
,
test: /\.(eot|ttf|svg|gif|png|jpg|otf|woff|woff2)$/,
loader: 'url-loader',
,
],
,
devServer:
contentBase: path.resolve(__dirname), // New
historyApiFallback: true,
,
plugins: [
new webpack.DefinePlugin(
'process.env.NODE_ENV': JSON.stringify('development'),
),
new webpack.HotModuleReplacementPlugin(),
],
);
index.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import createHistory from 'history/createBrowserHistory';
import createStore, combineReducers, applyMiddleware from 'redux';
import ConnectedRouter, routerReducer, routerMiddleware from 'react-router-redux';
import Provider from 'react-redux';
import AppContainer from 'react-hot-loader';
import createSagaMiddleware from 'redux-saga';
import composeWithDevTools from 'redux-devtools-extension/developmentOnly';
import 'bootstrap';
import 'styles/custom.scss';
import App from 'App';
import reducers from 'state';
import sagas from 'sagas';
const history = createHistory();
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
combineReducers(
...reducers,
router: routerReducer,
),
composeWithDevTools(applyMiddleware(routerMiddleware(history), sagaMiddleware)),
);
if (module.hot)
module.hot.accept('state', () =>
store.replaceReducer(require('state').default);
);
sagaMiddleware.run(sagas);
const render = (Component) =>
ReactDOM.render(
<AppContainer>
<Provider store=store>
<ConnectedRouter history=history>
<Component />
</ConnectedRouter>
</Provider>
</AppContainer>,
document.getElementById('app'),
);
;
render(App);
if (module.hot)
module.hot.accept('App', () => render(App); );
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
<div id="app">
</div>
<script type="text/javascript" src="/bundle.js"></script>
</body>
</html>
【问题讨论】:
【参考方案1】:-
您可以使用
react-script
和react-app-rewire-hot-loader
你可能不会使用react-hot-loader/babel
test: /\.(js|jsx)$/,
include: paths.appSrc,
loader: require.resolve("babel-loader"),
options:
// This is a feature of babel-loader for webpack (not Babel itself).
// It enables caching results in ./node_modules/.cache/babel-loader/
// directory for faster rebuilds.
cacheDirectory: true,
plugins: ["react-hot-loader/babel"]
,
【讨论】:
react-hot-loader/babel
定义在.babelrc
【参考方案2】:
您是否尝试过将根组件导出为热组件:
import hot from "react-hot-loader"
const App = () => <h3>Hello World</h3>
export default hot(module)(App)
【讨论】:
【参考方案3】:您定义了两次Hot Module Replacement。您在package.json
中定义了--hot
参数,然后在webpack.config.js
中定义了new webpack.HotModuleReplacementPlugin()
。你应该只定义一次。
【讨论】:
以上是关于react-hot-loader 和 webpack-dev-server 不会重新加载更改的主要内容,如果未能解决你的问题,请参考以下文章
如何让 react-hot-loader 与 webpack 2 和 webpackDevMiddleware 一起工作?
无法使 react-hot-loader 和 webpack-dev-server 与 react-router 一起工作
react-hot-loader: 未检测到 react-????-dom 补丁