I'm trying to correctly setup webpacks HMR, I'm developing a small app in order to learn how to use Redux in a React application.
I ran into a problem with webpack and the HMR plugin, when implementing the module.hot.accept
function everything seems to work fine, but I've noticed it that when I modify a dependency of my App
component it only re-renders the view when I don't pass any dependency argument to module.hot.accept
as specified in webpack's docs.
This is what the documentation says I should do:
module.hot.accept(
dependencies, // Either a string or an array of strings
callback // Function to fire when the dependencies are updated
)
This is what I'm trying to do, this doesn't work.
module.hot.accept('./components/App', () => {
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
})
module.hot.accept('./reducers', () => {
// Reconfigure the store
})
This one works
module.hot.accept(() => {
// Render function
})
So let's say my App
component, the one I render as child of the <Provider>
imports a Header
component and just renders like so:
const App = () => (
<div>
<Header />
</div>
)
then if I edit Header
the browser will only re-render the view if there's no dependency in module.hot.accept
The problem here is that if I don't pass any dependency it will try to reload my store object and that fires this warning: <Provider> does not support changing 'store' on the fly
, I want to properly configure webpack so it only updates the store object when I change things on my reducers and the view when I make changes to my components or containers.
* Edit * Little bit of extra info, webpack seems to be aware of updates bc it logs in console the updated modules, however doesn't rerenders anything.
This is my webpack.config.js
const path = require('path')
const webpack = require('webpack')
const namedModules = new webpack.NamedModulesPlugin();
const hotModuleReplacement = new webpack.HotModuleReplacementPlugin();
const config = {
context: path.resolve(__dirname, 'src'),
entry: './index.jsx',
devtool: 'eval-source-map',
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.(js|jsx)$/,
include: path.resolve(__dirname, 'src'),
use: [{
loader: 'babel-loader',
options: {
presets: [
['env', {'es2015': {'modules': false}}],
'react'
],
plugins: [
'transform-object-rest-spread',
]
}
}]
}]
},
resolve: {
extensions: ['.js', '.jsx', '.json', '*'],
modules: [
'node_modules'
]
},
plugins: [
namedModules,
hotModuleReplacement
],
devServer: {
port: 9000,
host: 'localhost',
inline: true,
hot: true
}
}
module.exports = config
Thanks in advance, fine developers.
So it was the babel configuration as I thought, you need the option modules: false
in the babel configuration so it lets webpack handle the modules, it is a noob mistake but man, it drove me crazy for days.
Turned out I was doing something wrong in this line of the babel presets:
['env', {'es2015': {'modules': false}}]
the correct configuration is:
['env', {modules: false}]