HMR and Hot Reloading with the webpack-dev-server
The webpack-dev-server
provides:
- Speedy compilation of client side assets
- Optional HMR which means that the page will reload automatically when after compilation completes. Note, some developers do not like this, as you'll abruptly lose any tweaks within the Chrome development tools.
- Optional hot-reloading. The older
react-hot-loader
has been deprecated in favor of fast-refresh. For use with Webpack, see Client Side rendering and HMR using react-refresh-webpack-plugin section below or visit react-refresh-webpack-plugin for additional details.
If you are not using server-side rendering (not using prerender: true
),
then you can follow all the regular docs for using the bin/shakapacker-dev-server
during development.
Server Side Rendering with the Default shakacode/shakapacker bin/shakapacker-dev-server
If you are using server-side rendering, then you have a couple of options. The recommended technique is to have a different Webpack configuration for server rendering.
If you use the same Webpack setup for your server and client bundles
If you do use the webpack-dev-server
for prerendering, be sure to set the
config/initializers/react_on_rails.rb
setting of
config.same_bundle_for_client_and_server = true
dev_server.hmr
maps to devServer.hot.
This must be false if you're using the webpack-dev-server for client and server bundles.
dev_server.inline
maps to devServer.inline.
This must also be false.
If you don't configure these two to false, you'll see errors like:
ReferenceError: window is not defined
(ifhmr
is true)TypeError: Cannot read property 'prototype' of undefined
(ifinline
is true)
Client-Side rendering with HMR using react-refresh-webpack-plugin
Basic installation
To enable the HMR functionality, you have to use ./bin/shakapacker-dev-server
-
In
config/shakapacker.yml
sethmr
andinline
dev_server
properties to true.dev_server: https: false host: localhost port: 3035 public: localhost:3035 hmr: true # Inline should be set to true if using HMR inline: true
-
Add react-refresh packages:
yarn add -D @pmmmwh/react-refresh-webpack-plugin react-refresh
-
HMR is for use with the
webpack-dev-server
, so we only add this for thewebpack-dev-server
.const { devServer } = require('shakapacker'); const isWebpackDevServer = process.env.WEBPACK_DEV_SERVER; // plugins if (isWebpackDevServer) { environment.plugins.append( 'ReactRefreshWebpackPlugin', new ReactRefreshWebpackPlugin({ overlay: { sockPort: devServer.port, }, }), ); }
We added
overlay.sockPort
option inReactRefreshWebpackPlugin
to match the webpack-dev-server port specified inconfig/shakapacker.yml
. This makes SockJS works properly and fixes this error in browser console:GET http://localhost:[port]/sockjs-node/info?t=[xxxxxxxxxx] 404 (Not Found)
. -
Add the react-refresh plugin in
babel.config.js
module.exports = function (api) { return { plugins: [process.env.WEBPACK_DEV_SERVER && 'react-refresh/babel'].filter(Boolean), }; };
That's it :).
Now the browser should reflect changes in .js
and .css
files without reloading.
If for some reason the plugin doesn't work, you can revert the changes and leave only devServer hmr
/inline
set to true, affecting only CSS files.
These plugins are working and tested with
- babel 7
- webpacker 5
- bootstrap 4
- jest 26
- core-js 3
- node 12.10.0
- [email protected]
- react-refresh 0.8.3
- react_on_rails 11.1.4
configuration.