reactjs - React Hot Reload with React-hot-loader 3, React-router 4, and Webpack-hot-middleware -
i trying make react-hot-loader 3 work react-hot-loader 3, react-router 4 , webpack-hot-middleware (last version, 2.18.2).
here server.js
:
const express = require('express'); const bodyparser = require('body-parser'); const cookiesmiddleware = require('universal-cookie-express'); /* eslint-disable import/no-extraneous-dependencies */ const webpack = require('webpack'); const webpackdevmiddleware = require('webpack-dev-middleware'); const webpackhotmiddleware = require('webpack-hot-middleware'); const webpackhotservermiddleware = require('webpack-hot-server-middleware'); /* eslint-enable import/no-extraneous-dependencies */ const clientconfig = require('./webpack.config.dev.client'); const serverconfig = require('./webpack.config.dev.server'); const port_number = process.env.port || 3000; const app = express(); app.use(bodyparser.urlencoded({ extended: true })); app.use(cookiesmiddleware()); app.use(express.static('public')); const multicompiler = webpack([clientconfig, serverconfig]); const clientcompiler = multicompiler.compilers[0]; app.use(webpackdevmiddleware(multicompiler, { publicpath: clientconfig.output.publicpath, noinfo: true, stats: { children: false }, })); app.use(webpackhotmiddleware(clientcompiler)); app.use(webpackhotservermiddleware(multicompiler, { serverrendereroptions: { outputpath: clientconfig.output.path }, })); app.listen(port_number, () => { // eslint-disable-next-line no-console console.log(`server listening @ port ${port_number}`); });
my client entry point
:
import react 'react'; import { render } 'react-dom'; import { appcontainer } 'react-hot-loader'; import * bundles './components/bundles'; import app './app'; const dorender = () => { render( <appcontainer> <app type="client" /> </appcontainer>, document.getelementbyid('content'), ); }; const splitpoints = window.splitpoints || []; promise.all(splitpoints.map(chunk => bundles[chunk].loadcomponent())) .then(dorender); if (module.hot) { module.hot.accept('./app', dorender); }
.babelrc
:
{ "plugins": [ "transform-decorators-legacy", "transform-object-rest-spread" ], "presets": [ ["es2015", { "modules": false }], "react", "stage-0" ], "env": { "development": { "plugins": ["react-hot-loader/babel"] }, "test": { "plugins": ["transform-es2015-modules-commonjs"] } } }
it looks followed every step of react-hot-loader's readme, yet everytime change code in component, message in console:
[hmr] bundle rebuilding client.js:207 [hmr] bundle rebuilt in 8218ms process-update.js:27 [hmr] checking updates on server... process-update.js:81 [hmr] following modules couldn't hot updated: (full reload needed) because modules have changed (and parents) not know how hot reload themselves. see http://webpack.github.io/docs/hot-module-replacement-with-webpack.html more details.
has stumbled on one? in advance!
edit: here client webpack config:
const path = require('path'); const webpack = require('webpack'); const autoprefixer = require('autoprefixer'); const stylelintplugin = require('stylelint-webpack-plugin'); const notifier = require('node-notifier'); const configfilename = './.env.development.json'; let envconfig; try { // eslint-disable-next-line import/no-dynamic-require, global-require envconfig = require(configfilename); } catch (e) { envconfig = {}; } const eslintsettings = { extends: path.join(__dirname, '.eslintrc.js'), configfile: path.join(__dirname, '.eslintrc.js'), emitwarning: true, cache: true, }; const babelsettings = { extends: path.join(__dirname, '.babelrc'), cachedirectory: true, }; const excludes = [ /node_modules(?![/\\]@local-package[/\\])/, ]; const roots = [ path.join(__dirname, '../../node_modules'), path.join(__dirname, 'node_modules'), path.join(__dirname, 'client'), ]; const getcommoncssloaders = enablecssmodules => [ { loader: 'style-loader', }, { loader: 'css-loader', options: { modules: enablecssmodules, importloaders: 1, localidentname: '[name]_[local]_[hash:base64:3]', }, }, { loader: 'postcss-loader', options: { sourcemap: true, ident: 'postcss', plugins: () => [ // eslint-disable-next-line global-require, import/no-extraneous-dependencies require('postcss-flexbugs-fixes'), autoprefixer({ env: 'development', flexbox: 'no-2009', }), ], }, }, ]; const rules = [ { enforce: 'pre', test: /\.js$/, exclude: /node_modules/, loader: 'eslint-loader', options: eslintsettings, }, { test: /\.js$/, exclude: excludes, loader: 'babel-loader', options: babelsettings, }, { test: /\.css$/, exclude: excludes, use: [ ...getcommoncssloaders(true), ], }, { test: /\.css$/, include: excludes, use: [ ...getcommoncssloaders(false), ], }, { test: /\.scss$/, exclude: excludes, use: [ ...getcommoncssloaders(true), { loader: 'resolve-url-loader', }, { loader: 'sass-loader', options: { sourcemap: true, }, }, ], }, { test: /.*\.(eot|woff|woff2|ttf|svg|png|jpe?g|gif)$/i, use: [ { loader: 'url-loader', options: { name: 'images/[name].[hash].[ext]', limit: 20000, }, }, { loader: 'image-webpack-loader', options: { mozjpeg: { quality: 80, }, pngquant: { quality: '80-90', }, bypassondebug: true, }, }, ], }, ]; const plugins = [ new webpack.loaderoptionsplugin({ debug: true, }), new webpack.hotmodulereplacementplugin(), new webpack.noemitonerrorsplugin(), new stylelintplugin({ configfile: path.join(__dirname, '.stylelintrc.js'), files: [ '**/*.s?(a|c)ss', '../shared/**/*.s?(a|c)ss', ], emiterrors: false, }), new webpack.normalmodulereplacementplugin(/\/components\/bundles/, './components/asyncbundles'), new webpack.normalmodulereplacementplugin(/\/bundles/, './asyncbundles'), new webpack.optimize.commonschunkplugin({ name: 'client', async: 'common', children: true, minchunks: (module, count) => { if (module.resource && (/^.*\.(css|scss)$/).test(module.resource)) { return false; } return count >= 3 && module.context && !module.context.includes('node_modules'); }, }), new webpack.optimize.commonschunkplugin({ name: 'client', children: true, minchunks: module => module.context && module.context.includes('node_modules'), }), new webpack.optimize.commonschunkplugin({ name: 'vendors', minchunks: module => module.context && module.context.includes('node_modules'), }), new webpack.ignoreplugin(/^\.\/locale$/, /moment$/), // eslint-disable-next-line func-names function () { this.plugin('done', (stats) => { notifier.notify({ title: 'webpack : build succeeded', message: `${stats.compilation.errors.length} error(s) - ${stats.compilation.warnings.length} warning(s)`, }); }); this.plugin('failed', () => { notifier.notify({ title: 'webpack', message: 'build failed hard', }); }); }, ]; const config = { name: 'client', target: 'web', devtool: 'inline-source-map', entry: ['webpack-hot-middleware/client', 'react-hot-loader/patch', './client/src/entry/js/polyfills', './client/src/entry/js/client'], output: { filename: 'client/[name].js', chunkfilename: 'client/chunks/[name].chunk.js', path: path.join(__dirname, 'public/dist'), publicpath: '/dist/', pathinfo: true, }, module: { rules, }, plugins, resolve: { modules: roots, }, resolveloader: { modules: roots, }, node: { fs: 'empty', net: 'empty', tls: 'empty', }, }; module.exports = config;
maybe has webpack.config file? have hot stuff setup in entry?
const config = { entry: [ 'babel-polyfill', 'react-hot-loader/patch', // activate hmr react `webpack-hot-middleware/client?path=http://${host}:${port}/__webpack_hmr`, // bundle client webpack-hot-middleware , connect provided endpoint './src/client.jsx', ],
i've had better luck using hapi server webpack-hot-middleware , webpack-dev-middleware. here snippet
import webpack 'webpack'; import hapiwebpackplugin 'hapi-webpack-plugin'; const config = require('../../../webpack.config.js'); // eslint-disable-line global-require const compiler = webpack(config); const options = { assets: { // webpack-dev-middleware options - https://github.com/webpack/webpack-dev-middleware index: '/public/index.html', }, hot: { // webpack-hot-middleware options - https://github.com/glenjamin/webpack-hot-middleware }, compiler, }; server.register({ register: hapiwebpackplugin, options, }, (error) => { if (error) { console.error(error); } });
if want try hapi, check out hapi-react-hot-loader-example
here full webpack.config
const path = require('path'); const webpack = require('webpack'); const copywebpackplugin = require('copy-webpack-plugin'); const extracttextplugin = require('extract-text-webpack-plugin'); const htmlwebpackplugin = require('html-webpack-plugin'); const progressbarplugin = require('progress-bar-webpack-plugin'); const htmlwebpackharddiskplugin = require('html-webpack-harddisk-plugin'); const robotstxtplugin = require('robotstxt-webpack-plugin').default; const port = process.env.port || 3000; const host = process.env.host || 'localhost'; const node_env = process.env.node_env || 'production'; const isproduction = (node_env === 'production'); const isdevelopment = (node_env === 'development'); const config = { entry: isdevelopment ? [ 'babel-polyfill', 'react-hot-loader/patch', // activate hmr react `webpack-hot-middleware/client?path=http://${host}:${port}/__webpack_hmr`, // bundle client webpack-hot-middleware , connect provided endpoint './src/client.jsx', ] : [ 'babel-polyfill', './src/client.jsx', ], resolve: { extensions: ['.js', '.jsx', '.json'], }, output: { path: path.join(__dirname, 'dist/public/'), filename: isdevelopment ? 'main.js' : 'assets/scripts/[name].[chunkhash].js', }, module: { rules: [ { test: /\.css$/, use: ['css-hot-loader'].concat( extracttextplugin.extract({ fallback: 'style-loader', use: [ { loader: 'css-loader', options: {minimize: true}, }, { loader: 'postcss-loader', }, ], }) ), }, { test: /\.jsx?$/, use: ['babel-loader'], include: path.join(__dirname, 'src'), }, ], }, plugins: [ new progressbarplugin(), new webpack.defineplugin({ 'process.env.node_env': json.stringify(node_env), }), isdevelopment ? null : new webpack.optimize.moduleconcatenationplugin(), isdevelopment ? new webpack.hotmodulereplacementplugin() // enable hmr globally : null, isdevelopment ? new webpack.namedmodulesplugin() // prints more readable module names in browser console on hmr updates : null, isdevelopment ? new webpack.noemitonerrorsplugin() // not emit compiled assets include errors : null, new extracttextplugin({ filename: isdevelopment ? 'assets/styles/main.css' : 'assets/styles/[name].[chunkhash].css', }), isdevelopment ? null : new webpack.optimize.commonschunkplugin({ name: 'vendor', minchunks: module => /node_modules/.test(module.resource), }), isdevelopment ? null : new webpack.optimize.commonschunkplugin({name: 'manifest'}), isproduction ? new webpack.optimize.uglifyjsplugin() : null, new htmlwebpackplugin({ template: path.resolve(__dirname, 'src/index.html'), minify: isproduction ? {collapsewhitespace: true, collapseinlinetagwhitespace: true} : false, alwayswritetodisk: true, }), new htmlwebpackharddiskplugin(), new copywebpackplugin([ { context: 'src/assets/media', from: '**/*', to: 'assets/media', }, ]), new robotstxtplugin({ policy: [ isproduction ? {useragent: '*', allow: '/'} : {useragent: '*', disallow: '/'}, ], }), ].filter(boolean), devtool: isproduction ? 'none' : 'cheap-module-eval-source-map', performance: { maxassetsize: 500000, }, }; module.exports = config;
Comments
Post a Comment