Skip to content

Commit a666689

Browse files
justin808alex35mil
authored andcommitted
Fix testing issues with Rails hot reloading setup
Configured testing so that: * If we're not running a webpack process to watch the client JS files, then we build the client or server files. * Test will let you know if it's skipping building. Expression used to see if a watch process is running: `pgrep -fl '\\-w \\-\\-config webpack\\.#{type}\\.rails\\.build\\.config\\.js'` * Renamed asset helpers so usage is like this: <%= env_stylesheet_link_tag 'application_prod', 'application_dev', media: 'all', 'data-turbolinks-track' => true %> <%= env_javascript_include_tag nil, 'http://localhost:3500/vendor-bundle.js' %> <%= env_javascript_include_tag nil, 'http://localhost:3500/app-bundle.js' %> <%= env_javascript_include_tag 'application_prod', 'application_dev', 'data-turbolinks-track' => true %> TODO: Should we consider having tests use the Rails hot reload server? Remove building bundles from install script Since the new spec configuration does it. Fix scss linter errors Had to turn off SelectorFormat since css modules require JS style names. Fix typo
1 parent c7577bd commit a666689

26 files changed

+119
-46
lines changed

.scss-lint.yml

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
scss_files:
44
- 'app/assets/stylesheets/**/*.scss'
5-
- 'client/assets/stylesheets/**/*.scss'
5+
- 'client/app/**/*.scss'
6+
7+
exclude: 'client/node_modules/**'
68

79
linters:
810
# BangFormat:
@@ -132,8 +134,8 @@ linters:
132134
# enabled: true
133135
# max_depth: 3
134136
#
135-
# SelectorFormat:
136-
# enabled: true
137+
SelectorFormat:
138+
enabled: false
137139
# convention: hyphenated_lowercase # or 'strict_BEM', or 'hyphenated_BEM', or 'snake_case', or 'camel_case', or a regex pattern
138140
#
139141
# Shorthand:

.travis.yml

-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ install:
1818
- nvm install 5.0
1919
- nvm use 5.0
2020
- npm install
21-
- cd client && npm run build:client
22-
- npm run build:server
2321
before_script:
2422
- export DISPLAY=:99.0
2523
- sh -e /etc/init.d/xvfb start

Procfile.dev

+7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
web: rails s
2+
3+
# Run the hot reload server for client development
24
client: sh -c 'rm app/assets/webpack/* || true && cd client && HOT_RAILS_PORT=3500 npm run build:dev:client'
5+
6+
# Keep the JS fresh for specs
7+
client-spec: sh -c 'cd client && npm run build:test:client'
8+
9+
# Keep the JS fresh for server rendering
310
server: sh -c 'cd client && npm run build:dev:server'
411
hot: sh -c 'cd client && HOT_PORT=4000 npm start'

README.md

+7-4
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,14 @@ Note that it's important to run the Rails server on a different port than the no
127127

128128
# Webpack configuration
129129
## Config Files
130+
130131
- `webpack.client.base.config.js`: Common configuration file to minimize code duplication for client.rails and client.hot.
131-
- `webpack.client.rails.config.js`: Used to generate the Rails bundles for Rails use.
132-
- `webpack.client.hot.config.js`: Used by server.js to run the Webpack Dev server.
133-
- `webpack.server.rails.config.js`: Common configuration file to minimize code duplication
134-
between the HMR and Rails configurations.
132+
- `webpack.client.rails.build.config.js`: Client side js bundle.
133+
- `webpack.server.rails.build.config.js`: Server side js bundle
134+
135+
These are used for hot reloading (Webpack Dev Server):
136+
- `webpack.client.rails.hot.config.js`: Used to generate the Rails bundles for Rails use so you get hot reloading within your Rails app.
137+
- `webpack.client.hot.config.js`: Used by server.js to run the Webpack Dev server for stubbing the api end points
135138

136139
## Webpack Resources
137140
- Good overview: [Pete Hunt's Webpack Howto](https://github.com/petehunt/webpack-howto)

app/assets/javascripts/application_dev.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
// It's important to include them in layout view above this asset
1515
// b/c it exposes jQuery for turbolinks and another non-webpack JS (if any)
1616

17-
// This one depend on jQuery
17+
// This one depends on jQuery
1818
//= require turbolinks
1919

20+
// This will soon be removed as it will be in vendor-bundle with react_on_rails 2.0
2021
//= require react_on_rails
2122

2223
//= require rails_startup

app/helpers/application_helper.rb

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
module ApplicationHelper
2-
def javascript_include_env_tag(asset, dev_asset, params = {})
3-
asset_file = Rails.env.production? ? asset : dev_asset
2+
# TODO: MOVE TO helper in react_on_rails
3+
# See application.html.erb for usage example
4+
def env_javascript_include_tag(prod_asset, dev_asset, params = {})
5+
asset_file = !Rails.env.development? ? prod_asset : dev_asset
46
return javascript_include_tag(asset_file, params) if asset_file
57
end
68

7-
def stylesheet_link_env_tag(asset, dev_asset, params = {})
8-
asset_file = Rails.env.production? ? asset : dev_asset
9+
# TODO: MOVE TO helper in react_on_rails
10+
def env_stylesheet_link_tag(prod_asset, dev_asset, params = {})
11+
asset_file = !Rails.env.development? ? prod_asset : dev_asset
912
return stylesheet_link_tag(asset_file, params) if asset_file
1013
end
1114
end

app/views/comments/show.html.erb

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
<div class="comment">
22
<p id="notice"><%= notice %></p>
33

4-
<p>
4+
<p class="js-comment-author">
55
<strong>Author:</strong>
66
<%= @comment.author %>
77
</p>
88

9-
<p>
9+
<p class="js-comment-text">
1010
<strong>Text:</strong>
1111
<%= @comment.text %>
1212
</p>

app/views/layouts/application.html.erb

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
<html>
33
<head>
44
<title>RailsReactTutorial</title>
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 %>
5+
<%= env_stylesheet_link_tag 'application_prod', 'application_dev', media: 'all', 'data-turbolinks-track' => true %>
6+
<%= env_javascript_include_tag nil, 'http://localhost:3500/vendor-bundle.js' %>
7+
<%= env_javascript_include_tag nil, 'http://localhost:3500/app-bundle.js' %>
8+
<%= env_javascript_include_tag 'application_prod', 'application_dev', 'data-turbolinks-track' => true %>
99
<%= csrf_meta_tags %>
1010
</head>
1111
<body>

app/views/pages/no_router.html.erb

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
<%= render "header" %>
44

55
<%= react_component('App', render(template: "/comments/index.json.jbuilder"),
6-
generator_function: true, prerender: true) %>
6+
generator_function: true, prerender: false) %>

client/app/assets/styles/app-variables.scss

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Defining application SASS variables in stand-alone file,
22
// so we can use them in bootstrap-loader and CSS Modules via sass-resources-loader
3-
$body-bg: #eff8fb; // background w/ character
4-
$navbar-default-bg: #ffffe0; // fancy yellow navbar
3+
$body-bg: #EFF8FB; // background w/ character
4+
$navbar-default-bg: #FFFFE0; // fancy yellow navbar
55
$font-size-base: 15px; // make it bigger!
66
$font-family-sans-serif: 'OpenSans-Light'; // apply custom font
77

Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
// These variables get loaded BEFORE Bootstrap thus overriding them in Bootstrap.
2-
@import "./app-variables";
2+
@import './app-variables';
33

44
// This path is relative to this file!
5-
$fonts-url-path: "../fonts";
5+
$fonts-url-path: '../fonts';
66

77
@font-face {
8-
font-family: "OpenSans-Light";
9-
src: url("#{$fonts-url-path}/OpenSans-Light.ttf") format("truetype");
8+
font-family: 'OpenSans-Light';
9+
src: url('#{$fonts-url-path}/OpenSans-Light.ttf') format('truetype');
1010
}

client/app/bundles/comments/components/CommentBox/CommentList/Comment/Comment.jsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ export default class Comment extends React.Component {
1616

1717
return (
1818
<div className={css.comment}>
19-
<h2 className={css.commentAuthor}>
19+
<h2 className={`${css.commentAuthor} js-comment-author`}>
2020
{author}
2121
</h2>
2222
<span
2323
dangerouslySetInnerHTML={{ __html: rawMarkup }}
24-
className="comment-text"
24+
className="js-comment-text"
2525
/>
2626
</div>
2727
);

client/app/bundles/comments/components/CommentScreen/CommentScreen.scss

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
}
44

55
.logo {
6-
background: url(./images/railsonmaui.png) no-repeat left bottom;
6+
background: url('./images/railsonmaui.png') no-repeat left bottom;
77
display: inline-block;
88
height: 40px;
99
margin-right: 10px;
1010
width: 146px;
1111
}
1212

1313
.twitterImage {
14-
background: url(./images/twitter_64.png) no-repeat;
14+
background: url('./images/twitter_64.png') no-repeat;
1515
height: 64px;
1616
width: 64px;
1717
}

client/package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@
2828
"test:debug": "npm run test -- --debug-brk",
2929
"start": "node server.js",
3030
"build:client": "NODE_ENV=production webpack --config webpack.client.rails.build.config.js",
31-
"build:server": "NODE_ENV=production webpack --config webpack.server.rails.config.js",
31+
"build:server": "NODE_ENV=production webpack --config webpack.server.rails.build.config.js",
3232
"build:dev:client": "babel-node server.rails.hot.js",
33-
"build:dev:server": "webpack -w --config webpack.server.rails.config.js",
33+
"build:dev:server": "webpack -w --config webpack.server.rails.build.config.js",
34+
"build:test:client": "webpack -w --config webpack.client.rails.build.config.js",
3435
"lint": "npm run eslint && npm run jscs",
3536
"eslint": "eslint --ext .js,.jsx .",
3637
"jscs": "jscs --verbose ."

client/webpack.client.base.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ module.exports = {
6262
// React is necessary for the client rendering
6363
{ test: require.resolve('react'), loader: 'expose?React' },
6464
{ test: require.resolve('react-dom'), loader: 'expose?ReactDOM' },
65+
{ test: require.resolve('jquery-ujs'), loader: 'imports?jQuery=jquery' },
6566
{ test: require.resolve('jquery'), loader: 'expose?jQuery' },
6667
{ test: require.resolve('jquery'), loader: 'expose?$' },
6768

config/application.rb

-3
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ class Application < Rails::Application
2020
# config.i18n.load_path += Dir[Rails.root.join("my", "locales", "*.{rb,yml}").to_s]
2121
# config.i18n.default_locale = :de
2222

23-
# Add folder with webpack generated assets to assets.paths
24-
config.assets.paths << Rails.root.join("app", "assets", "webpack")
25-
2623
# For not swallow errors in after_commit/after_rollback callbacks.
2724
config.active_record.raise_in_transactional_callbacks = true
2825
end

config/initializers/assets.rb

+6-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
# Version of your assets, change this if you want to expire all your assets.
44
Rails.application.config.assets.version = "1.0"
55

6-
# Add additional assets to the asset load path
7-
# Rails.application.config.assets.paths << Emoji.images_path
6+
# Add folder with webpack generated assets to assets.paths
7+
Rails.application.config.assets.paths << Rails.root.join("app", "assets", "webpack")
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_*.* )
11+
Rails.application.config.assets.precompile += %w(
12+
application_*.*
13+
server-bundle.js
14+
)

docs/testing-deployment.md

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Testing
2+
3+
1. `rake` runs the test suite
4+
2. To test production with precompiled assets:
5+
6+
```sh
7+
export SECRET_KEY_BASE=`rake secret`
8+
alias test-prod='rake assets:clobber && RAILS_ENV=production bin/rake assets:precompile \
9+
&& rails s -e production'
10+
```

lib/tasks/assets.rake

+8-2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,16 @@ namespace :assets do
1515
task :webpack do
1616
sh "cd client && npm run build:client"
1717
sh "cd client && npm run build:server"
18+
sh "mkdir -p public/assets"
19+
20+
# Critical to manually copy non js/css assets to public/assets as we don't want to fingerprint them
21+
sh "cp -rf app/assets/webpack/*.woff* app/assets/webpack/*.svg app/assets/webpack/*.ttf "\
22+
"app/assets/webpack/*.eot* public/assets"
23+
24+
# TODO: We should be gzipping these
1825
end
1926

2027
task :clobber do
21-
rm_rf "#{Rails.application.config.root}/app/assets/javascripts/generated/client-bundle.js"
22-
rm_rf "#{Rails.application.config.root}/app/assets/javascripts/generated/server-bundle.js"
28+
rm_rf "#{Rails.application.config.root}/app/assets/webpack"
2329
end
2430
end

lib/tasks/linters.rake

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ if %w(development test).include? Rails.env
3333
# end
3434

3535
SCSSLint::RakeTask.new do |t|
36-
t.files = ["app/assets/stylesheets/", "client/assets/stylesheets/"]
36+
t.files = ["app/assets/stylesheets/", "client/"]
3737
end
3838

3939
desc "eslint"

package.json

+7-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@
1111
"postinstall": "cd client && npm install",
1212
"test": "rspec && npm run test:client && npm run lint",
1313
"test:client": "(cd client && npm run test --silent)",
14-
"lint": "(cd client && npm run lint --silent)"
14+
"lint": "(cd client && npm run lint --silent)",
15+
"build:clean": "rm app/assets/webpack/*",
16+
"build:client": "(cd client && npm run build:client --silent)",
17+
"build:server": "(cd client && npm run build:server --silent)",
18+
"build:dev:client": "(cd client && npm run build:dev:client --silent)",
19+
"build:dev:server": "(cd client && npm run build:dev:server --silent)",
20+
"build:test:client": "(cd client && npm run build:test:client --silent)"
1521
},
1622
"repository": {
1723
"type": "git",

scripts/lint

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ ruby-lint app config spec
99
echo Linting with eslint and jscs
1010
(cd client && npm run lint)
1111

12-
scss-lint client/assets/stylesheets/*.scss app/assets/stylesheets/*.scss
12+
scss-lint client/**/*.scss app/assets/stylesheets/*.scss
1313

1414
echo Done linting with Rubocop, ruby-lint, eslint, jsrc, and slim-lint

spec/features/shared/examples.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
include_context "Form Submitted", name: :name, text: :text
99

1010
scenario "comment is added" do
11-
expect(page).to have_css(".comment", text: name)
12-
expect(page).to have_css(".comment", text: text)
11+
expect(page).to have_css(".js-comment-author", text: name)
12+
expect(page).to have_css(".js-comment-text", text: text)
1313
end
1414
end
1515

spec/rails_helper.rb

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
config.before(:suite) do
3838
DatabaseCleaner.strategy = :transaction
3939
DatabaseCleaner.clean_with :truncation
40+
41+
# Next line will ensure that assets are built if webpack -w is not running
42+
EnsureAssetsCompiled.check_built_assets
4043
end
4144

4245
config.around(:each) do |example|
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# TODO: Move to react_on_rails
2+
class EnsureAssetsCompiled
3+
def self.check_built_assets
4+
return if @checked_built_assets
5+
build_all_assets
6+
end
7+
8+
def self.running_webpack_watch?(type)
9+
running = `pgrep -fl '\\-w \\-\\-config webpack\\.#{type}\\.rails\\.build\\.config\\.js'`
10+
if running.present?
11+
puts "Found process, so skipping rebuild => #{running.ai}"
12+
return true
13+
end
14+
end
15+
16+
def self.build_assets_for_type(type)
17+
unless running_webpack_watch?(type)
18+
build_output = `cd client && npm run build:#{type}`
19+
if build_output =~ /error/i
20+
fail "Error in building assets!\n#{build_output}"
21+
else
22+
puts "Webpack build completed."
23+
end
24+
end
25+
end
26+
27+
def self.build_all_assets
28+
build_assets_for_type("client")
29+
build_assets_for_type("server")
30+
@checked_built_assets = true
31+
end
32+
end

0 commit comments

Comments
 (0)