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 bellow 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 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" (if hmr is true)
"TypeError: Cannot read property 'prototype' of undefined" (if inline is true)
Client Side rendering with HMR using react-refresh-webpack-plugin
Basic installation
To enable HMR functionality you have to use ./bin/shakapacker-dev-server
-
In
config/shakapacker.yml
set hmr and inlinedev_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 @pmmmwh/react-refresh-webpack-plugin react-refresh -D
-
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
. That way we make sockjs works properly and suppress error in browser consoleGET http://localhost:[port]/sockjs-node/info?t=[xxxxxxxxxx] 404 (Not Found)
. -
Add react-refresh plugin in
babel.config.js
module.export = function(api) {
return {
plugins: [process.env.WEBPACK_DEV_SERVER && 'react-refresh/babel'].filter(Boolean)
}
}
That's it :). Now Browser should reflect .js along with .css changes without reloading.
If by some reason plugin doesn't work you could revert changes and left only devServer hmr/inline 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.