I know the title doesn't make too much sense. But please bear with me.
I am setting up React for a legacy Rails app which is using the good old static ERBs. Due to the scale, I have to move towards SPA slowly, meaning swapping out components on the page.
My current setup is using webpack to compile a bundle file, the output it to the assets directory. Then just load that bundle file on the page relying on assets pipeline for caching (not idea, but enough to get started). On pages that have react component, I will have a <div>
for appending a certain component. e.g.:
<body>
<div>some other erb, html stuffs</div>
<div>more other erb, html stuffs</div>
<div id='react-component-1'></div>
<div id='react-component-2'></div>
</body>
This works as a basic setup. But to speed up the development, I'd like to setup hot loading. However, because I am not serving the entire page, I have to actually write the bundle file to disk so that rails can pick it up. And this also prevent me from using webpack-dev-server.
Is there any way to setup HMR in this setup?
Possible options:
- Reloading the bundle file every now and then (but I've tried this by appending new script tag, and removing the old one. Although the script file is downloaded (200 status from network tab), the updated scripts are not being loaded)
- Refreshing the page programmatically, and store serialize state in session storage (this won't be ideal, because it also refreshes other parts of the static page)
- Maybe there is a way to serve only the bundle file through webpack-dev-server?
Edit
I followed @SamHH answer and it seems it's not able to load the bundle file (404). My path config is a little quirky.
I have my webpack output path to
'../../app/assets/webpack/admin'
publicPath to
/admin/
But a matching path set in proxy
option didn't quite work. And from network tab, looks like it was loading from /javascripts/...
Webpack config:
const config = {
entry: {
bundle: './apps/appsRegistration',
vendor: VENDOR_LIBS
},
output: {
filename: '[name].js',
path: pathLib.resolve(__dirname, '../../app/assets/webpack/admin'),
publicPath: '/admin/'
},
resolve: {
extensions: ['.js', '.jsx'],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.EnvironmentPlugin({ NODE_ENV: 'development' }),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor'
}),
],
module: {
rules: [
{
test: /\.jsx?$/,
use: 'babel-loader',
exclude: /node_modules/,
},
],
},
externals: {
react: 'React',
'react-dom': 'ReactDOM',
redux: 'Redux',
'react-redux': 'ReactRedux',
'redux-thunk': 'ReduxThunk'
},
devServer: {
port: 9000,
disableHostCheck: true,
proxy: {
'!/admin/**': {
target: 'http://localhost:3000',
secure: false
}
},
hot: true
}
};