webpack-hot-middleware
webpack-hot-middleware copied to clipboard
multi compiler mode doesn't work.
webpack config
const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = [
{
name: 'app',
entry: {
app: [
'webpack-hot-middleware/client?name=app',
'./src/entry-app.js'
]
},
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
filename: '[name].js'
},
plugins: [
new HtmlWebpackPlugin(),
new webpack.HotModuleReplacementPlugin()
]
},
{
name: 'app2',
entry: {
app2: [
'webpack-hot-middleware/client?name=app2',
'./src/entry-app2.js'
]
},
output: {
path: path.resolve(__dirname, 'dist/app2'),
publicPath: '/app2',
filename: '[name].js'
},
plugins: [
new HtmlWebpackPlugin(),
new webpack.HotModuleReplacementPlugin()
]
}
]
server.js
const webpack = require('webpack')
const WebpackDevMiddleware = require('webpack-dev-middleware')
const WebpackHotMiddleware = require('webpack-hot-middleware')
const configs = require('./webpack.config')
const app = require('express')()
configs.forEach(c => {
const compiler = webpack(c)
const devMiddleware = WebpackDevMiddleware(compiler, {
publicPath: c.output.publicPath,
quiet: true
})
const hotMiddleware = WebpackHotMiddleware(compiler, { log: false, heartbeat: 2000 });
app.use(devMiddleware)
app.use(hotMiddleware)
})
app.listen(3000, err => {
if (err) throw err
console.log('Compiled successfully!')
console.log('You can view the application in browser.')
console.log()
console.log()
console.log('Local: http://localhost:3000')
})
First compiler works as expecting. But the second one, just give me this error,
I have never really used multi compiler setups, so don’t have much to add here.
But
Multi-compiler support in webpack is using one compiler instance with multiple configs passed to it
Here you have multiple distinct compiler instances - and you have them all under the same URL path, so the second one never receives any requests.
Try either:
- Using only one compiler instance
- setting public path to something different for each
- mounting the middleware at distinct subpaths
@glenjamin Based on my experiences in making this work for a similar setup, a solution here could be to allow specifying a custom URL part that each app/compiler uses for change detection. Do you think it would be possible?
To be more specific, changing the __webpack_hmr
part into something else.
You can set the path
option on client and server to do exactly that
I think I’ve figured out why. Apparently it all boils down to two things:
The first time it connects to the server, the events stream sends a “sync” event, but for such, there aren’t any hot-update manifests created (accordingly to Webpack source code, it’s skipped the first time).
So, https://github.com/webpack-contrib/webpack-hot-middleware/blob/f4353b9276019e36853134319f7384a198602b05/client.js#L267 Should read as:
if (applyUpdate && obj.action === “built”) {
Secondly, the middleware in the server side taps onDone to the “done” event, and in multi-compilations, not all done events mean anything changed, one needs to check if it was actually recorded to the compilation, and push nothing otherwise, here:
https://github.com/webpack-contrib/webpack-hot-middleware/blob/f4353b9276019e36853134319f7384a198602b05/middleware.js#L30
That part should be something like:
const action = statsResult.hash === (latestStats && latestStats.hash) ? “sync” : “build”;
latestStats = statsResult;
publishStats(action, latestStats, eventStream, opts.log);
Edit:
This last piece of code doesn’t work, latestStats
is always being null
, but we need to somehow check if the compilation changed hash. Also, it seems the first build also triggers the onDone
but I’m not sure what happens to that “build” event as it’s not getting to the client, perhaps because it’s too early for it to get there (no clients connected yet)
I was getting this same error in multi-compiler mode. I fixed it by using setting the name
for the client config to be exactly the same as the name setting for the compiler config. The path for both of my targets is the same, but it's worth noting that I have set an explicit path (full URL including hostname and port).
I was getting this same error in multi-compiler mode. I fixed it by using setting the
name
for the client config to be exactly the same as the name setting for the compiler config. The path for both of my targets is the same, but it's worth noting that I have set an explicit path (full URL including hostname and port).
Hi, @earksiinni! Can you show example of your config?
Hey, I came across this issue because we're running a multi-compiler for repo that has two apps on a shared server.
Ultimately, the hot middleware is doing unnecessary work because when both apps are running in hot mode, there are two different __webpack_hash__
values, one for each app.
The middleware is running at webpack-hot-middleware/client?path=/__webpack_hmr
for both of them, it would be cool if it would run on two paths, such as
webpack-hot-middleware/client?path=/__webpack_hmr_one
webpack-hot-middleware/client?path=/__webpack_hmr_two
but since we have just one server for two compilers, this change is only valid for the entry points in webpack config, not for the middleware itself, there it can only have one path. This basically results in one app getting incorrect events when the other changes. It doesn't perform a full reload of the non-updated app but fills the console with warnings. Which is not a big issues.
To me it sounds like solving the multicompiler conundrum is to have one path each compiler and make the middleware dispatch events only the the relevant channel.
I don't really know the webpack codebase much, so this is just an observation. ;)