Package Exports
- universal-hot-reload
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (universal-hot-reload) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
universal-hot-reload
Hot reload universally bundled webpack apps for the ultimate development experience 👏
If you universally bundle your app using webpack (i.e. you use webpack to bundle your server AND client side code) this package will set up hot reloading for both server and client side.
Why use this package?
- Automatic re-bundle on server code changes so server side rendering always reflect the latest changes.
- Automatic re-bundle on client code changes using webpack-dev-server.
This should be used in development only!
Installation
yarn add universal-hot-reload -D
Quickstart
Setup your server bundle webpack config like below. The important parts are:
- Set target to node.
- Excluding node_modules from the server bundle by setting externals using webpack-node-externals.
- Set libraryTarget to commonjs2 which adds module.exports to the beginning of the bundle, so universal-hot-reload can access your app.
const path = require('path'); const nodeExternals = require('webpack-node-externals'); module.exports = { mode: 'development', devtool: 'source-map', entry: './src/server/server.js', target: 'node', // Important externals: [nodeExternals()], // Important output: { path: path.resolve('dist'), filename: 'serverBundle.js', libraryTarget: 'commonjs2' // Important }, // other standard webpack config like loaders, plugins, etc... };
Setup your client bundle webpack config like below. Note that in output, publicPath must be the full url to the bundle:
const path = require('path'); const webpackServeUrl = 'http://localhost:3002'; module.exports = { mode: 'development', devtool: 'source-map', entry: './src/client/index', output: { path: path.resolve('dist'), publicPath: `${webpackServeUrl}/dist/`, // MUST BE FULL PATH with trailing slash! filename: 'bundle.js' }, module: { rules: [ { test: /\.jsx?$/, loader: 'babel-loader', include: path.resolve('src'), exclude: /node_modules/, options: { cacheDirectory: true, } }] }, };
In your server bootstrap, require universal-hot-reload and invoke it, passing it your server and client webpack config objects in that order:
const UniversalHotReload = require('universal-hot-reload').default; UniversalHotReload(require('path/to/webpack.server.config.js'), require('path/to/webpack.client.config.js'));
In your server entry file (as specified in your webpack server config "entry" property):
- In your html template for server rendering, the script reference to the client bundle should point to webpackServeUrl/dist/bundle.js.
- You must export your express app so universal-hot-reload can access the http.server object
import express from 'express'; const PORT = 3000; const app = express(); app.use('/dist', express.static('dist', {maxAge: '1d'})); // Important: reference webpack serve url for the client bundle const html = `<!DOCTYPE html> <html> <body> <div id="reactDiv">${reactString}</div> <script src="http://localhost:3002/dist/bundle.js"></script> </body> </html>`; // Important: the listen method returns a http.server object which must be default exported // so universal-hot-reload can access it export default app.listen(PORT, () => { log.info(`Listening at ${PORT}`); });
Run your app!
node src/server/index.js
Example
Check the example for a fully working spa with react and react-router.