如何使用webpack 2和webpackDevMiddleware获取react-hot-loader?
我使用的快递中间件代替的WebPack-dev的服务器:如何使用webpack 2和webpackDevMiddleware获取react-hot-loader?
const config = require("../webpack.config.js");
if(process.env.NODE_ENV === 'development') {
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const compiler = webpack(config);
app.use(webpackDevMiddleware(compiler, {
stats: {colors: true},
}));
app.use(webpackHotMiddleware(compiler));
}
我已经试过react-hot-loader/patch
,react-hot-loader/babel
和react-hot-loader/webpack
从[email protected]
:
module.exports = {
context: path.join(__dirname, 'client'),
entry: [
'webpack-hot-middleware/client',
'react-hot-loader/patch',
'./entry.less',
'./entry',
],
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js',
publicPath: '/',
},
module: {
rules: [
{
test: /\.jsx/,
use: [
{
loader: 'babel-loader',
options: {
plugins: ['transform-react-jsx', 'transform-class-properties', 'react-hot-loader/babel'],
},
},
'react-hot-loader/webpack'
],
},
但他们都不来工作。我刚刚得到这个错误信息:
[HMR]以下模块不能热更新:(全部重新加载需要) 这通常是因为它改变了模块(和他们的父母)不知道如何热重新加载自己。有关更多详细信息,请参阅http://webpack.github.io/docs/hot-module-replacement-with-webpack.html。 logUpdates @ bundle.js:29964 applyCallback @ bundle.js:29932 (匿名)@ bundle.js:29940个 bundle.js:29972
[HMR] - ./client/components/CrawlForm.jsx
使它工作的诀窍是什么?
N.B. CSS热加载工作得很好,所以我得到了这部分工作。
我花了好几天才终于破案。这里是我的代码工作:
的WebPack配置对象
const clientConfig = {
entry: {
client: [
'react-hot-loader/patch',
'webpack-hot-middleware/client',
'babel-polyfill',
'./src/client/client.js',
],
},
output: {
path: path.resolve(__dirname, './build/public'),
filename: '[name].js',
publicPath: '/',
},
devtool: 'inline-source-map',
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.LoaderOptionsPlugin({
debug: true,
}),
new CopyWebpackPlugin([
{ from: './src/assets/fonts', to: 'fonts' },
{ from: './src/assets/images', to: 'images' },
]),
new webpack.EnvironmentPlugin(['GOOGLE_MAP_API_KEY']),
],
module: {
rules: [
{
test: /(\.js|\.jsx)$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
presets: [['es2015', { loose: true }], 'react', 'stage-2'],
},
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
],
},
],
},
};
服务器index.js
我使用这两种开发中间件和热中间件和你一样。我也从react-hot-loader导入AppContainer
并包装我的组件。
import express from 'express';
import React from 'react';
import routes from 'components/Routes';
import html from './html';
import { renderToString } from 'react-dom/server';
import { match, RouterContext } from 'react-router';
import { Provider } from 'react-redux';
import makeStore from 'store';
import Immutable from 'immutable';
import setupNameless from './setupNameless';
import db from './database';
import { actions } from '../client/constants';
import webpack from 'webpack';
import webpackHotMiddleware from 'webpack-hot-middleware';
import webpackDevMiddleware from 'webpack-dev-middleware';
import { clientConfig as wpConfig } from '../../webpack.config.js';
import { AppContainer } from 'react-hot-loader';
import dotenv from 'dotenv';
dotenv.config();
const compiler = webpack(wpConfig);
db();
const app = express();
app.use(webpackDevMiddleware(compiler, {
publicPath: wpConfig.output.publicPath,
// noInfo: true,
stats: {
colors: true,
},
}));
app.use(webpackHotMiddleware(compiler));
app.use(express.static('build/public'));
const { commander: nameless, apiPrefix } = setupNameless(app);
app.use((req, res, next) => {
// make DB call here to fetch jobs.
nameless.exec('jobs', actions.GET_JOBS).then((jobs) => {
const store = makeStore(Immutable.fromJS({
// filters: {},
app: {
apiPrefix,
search: {
query: '',
options: {},
},
},
jobs,
}));
match({
routes,
location: req.originalUrl,
}, (error, redirectLocation, renderProps) => {
if (error) {
res.status(500).send(error.message);
} else if (redirectLocation) {
res.redirect(302, redirectLocation.pathname + redirectLocation.search);
} else if (renderProps) {
// You can also check renderProps.components or renderProps.routes for
// your "not found" component or route respectively, and send a 404 as
// below, if you're using a catch-all route.
try {
res.status(200).send(html(renderToString(
<AppContainer>
<Provider store={store}>
<RouterContext {...renderProps} />
</Provider>
</AppContainer>
), store.getState()));
} catch (err) {
next(err);
}
} else {
res.status(404).send('Not found');
}
});
}, (e) => {
next(e);
}).catch(e => {
next(e);
});
});
app.use(logErrors);
function logErrors(err, req, res, next) {
console.error(err.stack);
next(err);
}
app.listen(process.env.PORT || 3000,() => {
console.log(`App listening on port ${process.env.PORT || 3000}`);
});
Client.js
这是使它工作的法宝。我必须添加if (module.hot)
代码,并且还从react-hot-loader中导入AppContainer
。另一个重要方面是将key={Math.random()}
添加到我的<Router />
组件。
import { match, Router, browserHistory as history } from 'react-router';
import routes from './components/Routes';
import ReactDOM from 'react-dom';
import React from 'react';
import { Provider } from 'react-redux';
import makeStore from './store';
import Immutable from 'immutable';
import createLogger from 'redux-logger';
import createSagaMiddleware from 'redux-saga';
import sagas from './sagas';
import { AppContainer } from 'react-hot-loader';
const logger = createLogger();
const sagaMiddleware = createSagaMiddleware();
const store = makeStore(
Immutable.fromJS(window.__INITIAL_STATE__),
logger,
sagaMiddleware
);
sagaMiddleware.run(sagas);
ReactDOM.render(
<AppContainer>
<Provider store={store}>
<Router history={history} routes={routes} />
</Provider>
</AppContainer>,
document.getElementById('app'));
if (module.hot) {
module.hot.accept('./components/Routes',() => {
const nextRoutes = require('./components/Routes').default;
ReactDOM.render(
<AppContainer>
<Provider store={store}>
<Router key={Math.random()} history={history} routes={nextRoutes} />
</Provider>
</AppContainer>,
document.getElementById('app'));
});
}
好运
从Dan Abramov复述和realseanp借用一些代码,完整的说明是:
yarn add [email protected]
- 更新
webpack.config.js
:- 添加
react-hot-loader/patch
和webpack-hot-middleware/client
到您的entry
- 顶部添加
react-hot-loader/babel
您babel-loader
plugins
- 添加
new HotModuleReplacementPlugin()
到您的WebPack插件
- 添加
-
添加
webpack-dev-middleware
和webpack-hot-middlware
表示:// server/entry.jsx const express = require('express'); const path = require('path'); const cons = require('consolidate'); const fs = require('fs'); const port = 5469; const app = express(); app.disable('x-powered-by'); app.engine('hbs', cons.handlebars); app.set('view engine', 'hbs'); app.set('views', path.join(__dirname, '../views')); const wpConfig = require("../webpack.config.js"); if(process.env.NODE_ENV === 'development') { const webpack = require('webpack'); const webpackDevMiddleware = require('webpack-dev-middleware'); const webpackHotMiddleware = require('webpack-hot-middleware'); const compiler = webpack(wpConfig); app.use(webpackDevMiddleware(compiler, { stats: {colors: true}, })); app.use(webpackHotMiddleware(compiler)); } app.use(require('./routes')); app.use(express.static(wpConfig.output.path)); app.listen(port, function() { console.log(`Listening on http://localhost:${port}`); });
-
添加
<AppContainer>
和react.hot
到您的客户入口点:// client/entry.jsx import ReactDOM from 'react-dom'; import App from './components/App'; import { AppContainer } from 'react-hot-loader'; function render(Root) { ReactDOM.render(<AppContainer><Root/></AppContainer>, document.getElementById('react-root')); } render(App); if(module.hot) { module.hot.accept('./components/App',() => { render(require('./components/App').default); }); }
我遇到了一些麻烦误差叠加呈现运行时错误以及从中恢复。我注意到webpack-dev-server
在发生错误时会完全重新加载。
这可以用下面的代码片段进行模拟:
if (module.hot) module.hot.accept('./App',() => {
try {
render(App)
} catch (e) {
location.reload();
}
});
我的工作fork of react-hot-boilerplate可在Github上。
我还添加了每一个点,我的应用程序,但它没有工作 的问题是在publicPath
在我webpack.config.js
我有
publicPath: '/client/dist'
然后我改
publicPath: '/'
现在它的工作原理
哇...比以前更复杂了。 ''和'if(module.hot)'位为我工作。谢谢!! –
mpen