Redux无法热更新
wd2010 opened this issue · comments
wd2010 commented
看了作者的例子受益匪浅,我刚入门webpack,做练习的过程中我也自己用router4+react-loadable仿写了一个demo,但在reducer更改初始值时无法热更新,这是我的demo地址:https://github.com/wd2010/webpack-demo,请大神帮忙看看!
app.js(entry文件)
import React from 'react';
import {hydrate} from 'react-dom';
import configureStore from './store/configureStore';
import createHistory from 'history/createBrowserHistory'
import createApp from './store/createApp';
import Loadable from 'react-loadable';
const initialState = window.__INITIAL_STATE__;
let store=configureStore(initialState)
const history=createHistory()
const render=()=>{
let application=createApp({store,history});
hydrate(application,document.getElementById('root'))
}
window.main = () => {
Loadable.preloadReady().then(() => {
render()
});
};
configureStore.js
import {createStore, applyMiddleware,compose} from "redux";
import thunkMiddleware from "redux-thunk";
import createHistory from 'history/createMemoryHistory';
import { routerReducer, routerMiddleware } from 'react-router-redux'
import {composeWithDevTools} from 'redux-devtools-extension'
import rootReducer from './reducers/index';
const routerReducers=routerMiddleware(createHistory());//路由
const middleware=[thunkMiddleware,routerReducers];
let configureStore=(initialState)=>{
let store=createStore(rootReducer,initialState,composeWithDevTools(applyMiddleware(...middleware)));
//热加载配置
if(module.hot) {
console.log(module.hot.status())
module.hot.accept('./reducers/index.js', () => {
store.replaceReducer(rootReducer)
console.log('=',store.getState())
});
}
return store;
}
export default configureStore;
webpack.config.js
const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin"),
HtmlWebpackPlugin=require('html-webpack-plugin'),
ProgressBarPlugin = require('progress-bar-webpack-plugin');
const path=require('path');
const webpack=require('webpack');
import { ReactLoadablePlugin } from 'react-loadable/webpack';
const DIR_NAME=path.join(__dirname,'../');
const config={
context: DIR_NAME,
entry:{
bundle: ['./client/app.js','webpack-hot-middleware/client?path=/__webpack_hmr'],
vendor: ['react','react-dom','redux','react-redux'],
},
output:{
path: path.resolve(DIR_NAME,'./dist/client'),
filename: '[name].js',
chunkFilename: 'chunk.[name].js',
publicPath:'/'
},
resolve: {extensions: ['.js', '.jsx' ,'.json', '.scss']},
module:{
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader:'babel-loader',
options:{
presets: ['env', 'react', 'stage-0','react-hmre'],
plugins: ['transform-runtime', 'add-module-exports','syntax-dynamic-import','react-loadable/babel'],
cacheDirectory: true,
}
}
},{
test: /\.html$/,
exclude:/node_modules/,
loader: 'html-loader'
}
],
},
plugins:[
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new ProgressBarPlugin({summary: false}),
new webpack.optimize.CommonsChunkPlugin({
names:['vendor','manifest'],
filename:'[name].js',
}),
new HtmlWebpackPlugin({
filename: '../views/dev/index.html',
template: './views/tpl/index.html',
chunks: ['vendor','manifest', 'bundle'],
}),
new ReactLoadablePlugin({
filename: './views/dev/react-loadable.json',
}),
],
}
module.exports=config
clientRouter.js
import React from 'react';
import fs from 'fs';
import path from 'path';
import {renderToString} from 'react-dom/server';
import Loadable from 'react-loadable';
import { getBundles } from 'react-loadable/webpack';
import stats from '../../views/dev/react-loadable.json';
import {routesConfig} from '../../client/routes';
import configureStore from '../../client/store/configureStore';
import createHistory from 'history/createMemoryHistory'
import createApp from '../../client/store/createApp';
import {matchPath} from 'react-router-dom';
import {matchRoutes} from 'react-router-config';
import Helmet from 'react-helmet';
const store=configureStore();
const prepHTML=(data,{html,head,body,scripts,styles,state})=>{
data=data.replace('<html',`<html ${html}`);
data=data.replace('</head>',`${head} \n ${styles}</head>`);
data=data.replace('<div id="root"></div>',`<div id="root">${body}</div>`);
data=data.replace('<body>',`<body> \n <script>window.__INITIAL_STATE__ =${JSON.stringify(state)}</script>`);
data=data.replace('</body>',`${scripts}</body>`);
return data;
}
const markup=({ctx})=>{
let modules = [];
const history=createHistory({initialEntries:[ctx.req.url]})
let state=store.getState();
let appString= renderToString(
<Loadable.Capture report={moduleName => modules.push(moduleName)}>
{createApp({store,history})}
</Loadable.Capture>
)
let bundles = getBundles(stats, modules);
let scriptfiles = bundles.filter(bundle => bundle.file.endsWith('.js'));
let stylefiles = bundles.filter(bundle => bundle.file.endsWith('.css'));
let scripts=scriptfiles.map(script=>`<script src="/${script.file}"></script>`).join('\n');
let styles=stylefiles.map(style=>`<link href="/${style.file}" rel="stylesheet"/>`).join('\n');
let filePath=path.join(__dirname,'../../views/dev/index.html')
let htmlData=fs.readFileSync(filePath,'utf-8');
const helmet=Helmet.renderStatic();
let renderedHtml=prepHTML(htmlData,{
html:helmet.htmlAttributes.toString(),
head:helmet.title.toString()+helmet.meta.toString()+helmet.link.toString(),
body:appString,
scripts:scripts,
styles:styles,
state
})
return renderedHtml
}
const getMatch=(routesArray, url)=>{
return routesArray.some(router=>matchPath(url,{
path: router.props.path,
exact: router.props.exact,
}))
}
const clientRouter=async(ctx,next)=>{
let isMatch=getMatch(routesConfig,ctx.req.url);
if(isMatch){
let renderedHtml=markup({ctx});
ctx.body=renderedHtml
}else{
await next()
}
}
export default clientRouter;
更改reducer初始值时,console.log输出值
[HMR] connected
bundle.js:6781 [HMR] bundle rebuilding
bundle.js:6789 [HMR] bundle rebuilt in 180ms
bundle.js:7715 [HMR] Checking for updates on the server...
bundle.js:7788 [HMR] Updated modules:
bundle.js:7790 [HMR] - ./client/store/reducers/home.js
bundle.js:7790 [HMR] - ./client/store/reducers/index.js
bundle.js:7795 [HMR] App is up to date.
bundle.js:6781 [HMR] bundle rebuilding
bundle.js:6789 [HMR] bundle rebuilt in 195ms
bundle.js:7715 [HMR] Checking for updates on the server...
bundle.js:7788 [HMR] Updated modules:
bundle.js:7790 [HMR] - ./client/store/reducers/home.js
bundle.js:7790 [HMR] - ./client/store/reducers/index.js
bundle.js:7795 [HMR] App is up to date.
bundle.js:6781 [HMR] bundle rebuilding
bundle.js:6789 [HMR] bundle rebuilt in 175ms
bundle.js:7715 [HMR] Checking for updates on the server...
bundle.js:7788 [HMR] Updated modules:
bundle.js:7790 [HMR] - ./client/store/reducers/home.js
bundle.js:7790 [HMR] - ./client/store/reducers/index.js
bundle.js:7795 [HMR] App is up to date.
Sam commented
I also encountered the same problem when using dva.