Last active
May 19, 2019 00:36
-
-
Save esamattis/28c2dbcbe8109a0c5edb to your computer and use it in GitHub Desktop.
React hot reloading with Webpack for Ruby on Rails
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script charset="utf-8"> | |
<% if ENV["RAILS_ENV"] == "production" %> | |
var script = "/react-app-bundle.js"; | |
<% else %> | |
console.warn("Development mode. Make sure to start 'node devServer.js'"); | |
var script = "http://" + (location.host || 'localhost').split(':')[0] + ":4000/react-app-bundle.js" | |
<% end %> | |
document.write('<script src="' + script + '"></' + 'script>'); | |
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var path = require("path"); | |
var express = require("express"); | |
var webpack = require("webpack"); | |
var config = require("./webpack.config"); | |
var app = express(); | |
var compiler = webpack(config); | |
app.use(require("webpack-dev-middleware")(compiler, { | |
noInfo: true, | |
publicPath: config.output.publicPath, | |
})); | |
app.use(require("webpack-hot-middleware")(compiler)); | |
app.listen(4000, "0.0.0.0", function(err) { | |
if (err) { | |
console.log(err); | |
return; | |
} | |
console.log("Listening at http://0.0.0.0:4000"); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var webpack = require("webpack"); | |
// This must be the public address where the hot reload bundle is loaded in the | |
// browser. Yeah it sucks to hard code it here. Let's hope for the better | |
// future | |
var PUBLIC_DEV_SERVER = "http://my-dev-server:4000/"; | |
var ENTRY = "./index.js"; | |
var NODE_ENV_PLUGIN = new webpack.DefinePlugin({ | |
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV) | |
}); | |
var config = { | |
entry: [ | |
"webpack-hot-middleware/client?path=" + PUBLIC_DEV_SERVER + "__webpack_hmr", | |
ENTRY | |
], | |
output: { | |
path: __dirname + "/public", | |
filename: "react-app-bundle.js", | |
publicPath: PUBLIC_DEV_SERVER | |
}, | |
devtool: "cheap-module-eval-source-map", | |
module: { | |
loaders: [ | |
{ | |
test: /\.jsx?$/, | |
exclude: /node_modules/, | |
loader: "babel", | |
query: { | |
"env": { | |
// Not active when NODE_ENV=production | |
"development": { | |
"plugins": ["react-transform"], | |
"extra": { | |
"react-transform": [{ | |
"target": "react-transform-hmr", | |
"imports": ["react"], | |
"locals": ["module"] | |
}] | |
} | |
} | |
} | |
} | |
} | |
] | |
}, | |
plugins: [ | |
NODE_ENV_PLUGIN, | |
new webpack.HotModuleReplacementPlugin(), | |
new webpack.NoErrorsPlugin(), | |
] | |
}; | |
// Drop all hot stuff for production! | |
if (process.env.NODE_ENV === "production") { | |
config.devtool = "source-map"; | |
config.entry = ENTRY; | |
delete config.output.publicPath; | |
config.plugins = [NODE_ENV_PLUGIN]; | |
} | |
module.exports = config; |
This helped me too. To get it to work, I had to make sure my config.output.path was absolute (path.join(__dirname,'relative/path/to/app.js')
), and my config structure was even a little different than @gugl's update above:
{
loader: 'babel-loader',
test: /\.(jsx?$)/,
exclude: /node_modules/,
query: {
"presets": ["es2015", "react"],
"plugins": [
'transform-class-properties',
'transform-decorators-legacy',
'transform-object-rest-spread',
'transform-object-assign',
'transform-async-to-generator'
],
"env": {
// this plugin will be included only in development mode, e.g.
// if NODE_ENV (or BABEL_ENV) environment variable is not set
// or is equal to "development"
"development": {
"plugins": [
// must be an array with options object as second item
["react-transform", {
// must be an array of objects
"transforms": [{
// can be an NPM module name or a local path
"transform": "react-transform-hmr",
// see transform docs for "imports" and "locals" dependencies
"imports": ["react"],
"locals": ["module"]
}]
}]
]
}
}
}
},
Last, to get hot module reload working with css while using postcss, I had to add postcss-import
to my css config in webpack using the code at the bottom of this thread.
This worked perfectly for me. I changed this line however:
var PUBLIC_DEV_SERVER = "http://my-dev-server:4000/";
Replaced it with so that it is agnostic of the devserver:
const os = require("os");
const PUBLIC_DEV_SERVER = `http://${os.hostname()}:4000/`;
Tried the same setup.. but end up with "EventSource's response has a MIME type ("text/html") that is not "text/event-stream". Aborting the connection." error. Any idea about this.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This works great! The one problem that I was experiencing was I didn't specify the path.