Reputation: 7768
The webpack config of a universal app usually is an array of config objects like:
module.exports = [
{
name: 'client',
entry: {
app: [...require("./loaders").hotLoaders, "./src/frontend/client"],
libs: [
'react', 'react-dom'
]
},
output: {
path: path.join(__dirname, "../../www"),
filename: "js/[name].bundle.js"
},
...
},
{
name: 'server',
target: 'node',
entry: {
server: ["./src/universal/server"],
express: ["./src/universal/express"]
},
output: {
path: path.join(__dirname, "../../www"),
filename: "js/[name].bundle.js"
}
...
}];
After running webpack --config build/webpack/prod.js
, I can do the following on production, just run the output of server.express chunk like node www/express.bundle.js
.
// src/universal/express.tsx
import SERVER from "./server"
const express = require("express");
const app = express();
app.use(express.static('www'));
app.use(require("morgan")('combined'));
app.use(SERVER);
app.listen(3000);
And for development I can node hot.js
and I get HMR working nice.
// hot.js
const app = require("express")();
const compiler = require('webpack')(require('./build/webpack/prod.js'));
app.use(require('webpack-dev-middleware')(compiler);
app.use(require('webpack-hot-middleware')(compiler.compilers.find(compiler => compiler.name === 'client')));
app.use(require("morgan")('combined'));
app.use(require("./www/server.bundle").default);
app.listen(3000);
HMR works very fast like this. But as soon as I start editing my files, react shows me warning about React attempted to reuse markup
. When the code changes, hmr does its magic but the server keep sending the old markup even with a hard refresh because I am hard requiring a bundle file like let SERVER = require("./www/server.bundle").default;
Maybe webpack-dev-server handles this, but how do I setup it with an array of webpack config?
I thought of making hot.js a chunk as well, but it calls require('./build/webpack/prod.js')
that calls require('webpack')
a lot, making webpack angry and not compiling anything.
Upvotes: 1
Views: 2103
Reputation: 7033
You might be interested in webpack-hot-server-middleware
which was designed to solve this very problem.
All you'd need to do is replace the hardcoded require('./www/server.bundle').default
with webpack-hot-server-middleware
, e.g.
const app = require("express")();
const compiler = require('webpack')(require('./build/webpack/prod.js'));
app.use(require('webpack-dev-middleware')(compiler);
app.use(require('webpack-hot-middleware')(compiler.compilers.find(compiler => compiler.name === 'client')));
app.use(require("morgan")('combined'));
app.use(require('webpack-hot-server-middleware')(compiler, { chunkName: 'server' });
app.listen(3000);
Webpack Hot Server Middleware will then make sure each request is passed to the most recent compilation of server.bundle.js
so you no longer have to restart your server during development.
Additionally, it has the added benefit of sharing the same Webpack cache as the client bundle for faster builds.
Upvotes: 2