Skip to content

Commit c088fc4

Browse files
committed
Make Rails development views hot reloadable
1 parent 98eb9d5 commit c088fc4

13 files changed

+170
-18
lines changed

Procfile.dev

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
web: rails s
2-
client: sh -c 'rm app/assets/webpack/* || true && cd client && npm run build:dev:client'
2+
client: sh -c 'rm app/assets/webpack/* || true && cd client && HOT_RAILS_PORT=3500 npm run build:dev:client'
33
server: sh -c 'cd client && npm run build:dev:server'
4-
hot: sh -c 'cd client && npm start'
4+
hot: sh -c 'cd client && HOT_PORT=4000 npm start'
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// This is a manifest file that'll be compiled into application.js, which will include all the files
2+
// listed below.
3+
//
4+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6+
//
7+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8+
// compiled file.
9+
//
10+
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11+
// about supported directives.
12+
13+
// All webpack assets in development will be loaded via webpack dev server
14+
// It's important to include them in layout view above this asset
15+
// b/c it exposes jQuery for turbolinks and another non-webpack JS (if any)
16+
17+
// This one depend on jQuery
18+
//= require turbolinks
19+
20+
//= require react_on_rails
21+
22+
//= require rails_startup

app/assets/javascripts/application.js renamed to app/assets/javascripts/application_prod.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,5 @@
1616
//= require vendor-bundle
1717
//= require app-bundle
1818

19-
// Next one depend on jQuery
20-
//= require turbolinks
21-
22-
//= require react_on_rails
23-
24-
//= require rails_startup
19+
// Non-webpack assets incl turbolinks
20+
//= require application_dev
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Any non webpack assets can be imported here
2+
// Others will be served via webpack-dev-server
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
// These assets are located in app/assets/webpack directory
22
@import 'vendor-bundle';
33
@import 'app-bundle';
4+
5+
// Non-webpack assets
6+
@import 'application_dev';

app/helpers/application_helper.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,11 @@
11
module ApplicationHelper
2+
def javascript_include_env_tag(asset, dev_asset, params = {})
3+
asset_file = Rails.env.production? ? asset : dev_asset
4+
return javascript_include_tag(asset_file, params) if asset_file
5+
end
6+
7+
def stylesheet_link_env_tag(asset, dev_asset, params = {})
8+
asset_file = Rails.env.production? ? asset : dev_asset
9+
return stylesheet_link_tag(asset_file, params) if asset_file
10+
end
211
end

app/views/layouts/application.html.erb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
<html>
33
<head>
44
<title>RailsReactTutorial</title>
5-
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
6-
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
5+
<%= stylesheet_link_env_tag 'application_prod', 'application_dev', media: 'all', 'data-turbolinks-track' => true %>
6+
<%= javascript_include_env_tag nil, 'http://localhost:3500/vendor-bundle.js' %>
7+
<%= javascript_include_env_tag nil, 'http://localhost:3500/app-bundle.js' %>
8+
<%= javascript_include_env_tag 'application_prod', 'application_dev', 'data-turbolinks-track' => true %>
79
<%= csrf_meta_tags %>
810
</head>
911
<body>

client/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@
2727
"test": "NODE_PATH=./app mocha --compilers js:babel-core/register --require ./app/libs/testHelper.js 'app/**/*.spec.@(js|jsx)'",
2828
"test:debug": "npm run test -- --debug-brk",
2929
"start": "node server.js",
30-
"build:client": "NODE_ENV=production webpack --config webpack.client.rails.config.js",
30+
"build:client": "NODE_ENV=production webpack --config webpack.client.rails.build.config.js",
3131
"build:server": "NODE_ENV=production webpack --config webpack.server.rails.config.js",
32-
"build:dev:client": "webpack -w --config webpack.client.rails.config.js",
32+
"build:dev:client": "babel-node server.rails.hot.js",
3333
"build:dev:server": "webpack -w --config webpack.server.rails.config.js",
3434
"lint": "npm run eslint && npm run jscs",
3535
"eslint": "eslint --ext .js,.jsx .",

client/server.rails.hot.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* eslint no-var: 0, no-console: 0 */
2+
3+
import webpack from 'webpack';
4+
import WebpackDevServer from 'webpack-dev-server';
5+
6+
import webpackConfig from './webpack.client.rails.hot.config';
7+
8+
const hotRailsPort = process.env.HOT_RAILS_PORT || 3500;
9+
10+
const compiler = webpack(webpackConfig);
11+
12+
const devServer = new WebpackDevServer(compiler, {
13+
contentBase: 'http://lvh.me:' + hotRailsPort,
14+
publicPath: webpackConfig.output.publicPath,
15+
hot: true,
16+
inline: true,
17+
historyApiFallback: true,
18+
quiet: false,
19+
noInfo: false,
20+
lazy: false,
21+
stats: {
22+
colors: true,
23+
hash: false,
24+
version: false,
25+
chunks: false,
26+
children: false,
27+
},
28+
});
29+
30+
devServer.listen(3500, 'localhost', err => {
31+
if (err) console.error(err);
32+
console.log(
33+
'=> 🔥 Webpack development server is running on port ' + hotRailsPort
34+
);
35+
});

client/webpack.client.hot.config.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ const webpack = require('webpack');
55

66
const config = require('./webpack.client.base.config');
77

8+
const hotPort = process.env.HOT_PORT || 4000;
9+
810
config.entry.vendor.push('bootstrap-loader');
911
config.entry.app.push(
1012

1113
// Webpack dev server
12-
'webpack-dev-server/client?http://localhost:4000',
14+
'webpack-dev-server/client?http://localhost:' + hotPort,
1315
'webpack/hot/dev-server'
1416
);
1517

client/webpack.client.rails.config.js renamed to client/webpack.client.rails.build.config.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Run like this:
2-
// cd client && npm run build:dev:client
2+
// cd client && npm run build:client
33
// Note that Foreman (Procfile.dev) has also been configured to take care of this.
44

55
const webpack = require('webpack');
@@ -18,12 +18,10 @@ config.output = {
1818
config.entry.vendor.unshift(
1919
'es5-shim/es5-shim',
2020
'es5-shim/es5-sham',
21+
'jquery-ujs',
2122
'bootstrap-loader/extractStyles'
2223
);
2324

24-
// jquery-ujs MUST GO AFTER jquery, so must use 'push'
25-
config.entry.app.push('jquery-ujs');
26-
2725
// See webpack.common.config for adding modules common to both the webpack dev server and rails
2826

2927
config.module.loaders.push(
@@ -56,7 +54,7 @@ config.plugins.push(
5654

5755
if (devBuild) {
5856
console.log('Webpack dev build for Rails'); // eslint-disable-line no-console
59-
module.exports.devtool = 'eval-source-map';
57+
config.devtool = 'eval-source-map';
6058
} else {
6159
console.log('Webpack production build for Rails'); // eslint-disable-line no-console
6260
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Run with Rails server like this:
2+
// rails s
3+
// cd client && babel-node server.rails.hot.js
4+
// Note that Foreman (Procfile.dev) has also been configured to take care of this.
5+
6+
const path = require('path');
7+
const webpack = require('webpack');
8+
9+
const config = require('./webpack.client.base.config');
10+
11+
const hotRailsPort = process.env.HOT_RAILS_PORT || 3500;
12+
13+
config.entry.app.push(
14+
'webpack-dev-server/client?http://localhost:' + hotRailsPort,
15+
'webpack/hot/only-dev-server'
16+
);
17+
18+
config.entry.vendor.push(
19+
'es5-shim/es5-shim',
20+
'es5-shim/es5-sham',
21+
'jquery-ujs',
22+
'bootstrap-loader'
23+
);
24+
25+
config.output = {
26+
filename: '[name]-bundle.js',
27+
path: path.join(__dirname, 'public'),
28+
publicPath: `http://localhost:${hotRailsPort}/`,
29+
};
30+
31+
config.module.loaders.push(
32+
{
33+
test: /\.jsx?$/,
34+
loader: 'babel',
35+
exclude: /node_modules/,
36+
query: {
37+
plugins: [
38+
[
39+
'react-transform',
40+
{
41+
transforms: [
42+
{
43+
transform: 'react-transform-hmr',
44+
imports: ['react'],
45+
locals: ['module'],
46+
},
47+
],
48+
},
49+
],
50+
],
51+
},
52+
},
53+
{
54+
test: /\.css$/,
55+
loaders: [
56+
'style',
57+
'css?modules&importLoaders=1&localIdentName=[name]__[local]__[hash:base64:5]',
58+
'postcss',
59+
],
60+
},
61+
{
62+
test: /\.scss$/,
63+
loaders: [
64+
'style',
65+
'css?modules&importLoaders=3&localIdentName=[name]__[local]__[hash:base64:5]',
66+
'postcss',
67+
'sass',
68+
'sass-resources',
69+
],
70+
}
71+
);
72+
73+
config.plugins.push(
74+
new webpack.HotModuleReplacementPlugin(),
75+
new webpack.NoErrorsPlugin()
76+
);
77+
78+
config.devtool = 'eval-source-map';
79+
80+
console.log('Webpack dev build for Rails'); // eslint-disable-line no-console
81+
82+
module.exports = config;

config/initializers/assets.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@
88

99
# Precompile additional assets.
1010
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
11+
Rails.application.config.assets.precompile += %w( application_*.* )

0 commit comments

Comments
 (0)