Skip to content

Commit

Permalink
Fix express server rendering
Browse files Browse the repository at this point in the history
* Had to work around no shared store support
* See shakacode/react_on_rails#504
  • Loading branch information
justin808 committed Aug 1, 2016
1 parent a953b02 commit 94c72bd
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 18 deletions.
9 changes: 2 additions & 7 deletions Procfile.dev
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Basic procfile for dev work.
# Runs all processes. Development is faster if you pick one of the other Procfiles if you don't need
# some of the processes: Procfile.hot or Procfile.express
# Development is faster if you pick one of the other Procfiles if you don't need
# the processes to create the test files. Thus, run the `Procfile.hot` one instead

# Development rails requires both rails and rails-assets
# (and rails-server-assets if server rendering)
Expand All @@ -14,8 +14,3 @@ rails-static-client-assets: sh -c 'npm run build:dev:client'

# Render static client assets. Remove if not server rendering
rails-static-server-assets: sh -c 'npm run build:dev:server'

# Run an express server if you want to mock out your endpoints. No Rails involved!
# Disable this if you are not using it.
# It's a great way to prototype UI especially with non-Rails developers!
express: sh -c 'HOT_PORT=4000 npm start'
8 changes: 8 additions & 0 deletions Procfile.express
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,12 @@
# You can still run tests, and they will build the webpack file for each test run.
# Hot reloading of JS and CSS is enabled!

# UPDATE: 2016-07-31
# We no longer recommend using an express server with Rails. It's simply not necessary because:
# 1. Rails can hot reload
# 2. There's extra maintenance in keeping this synchronized.
# 3. React on Rails does not have a shared_store JS rendering:
# https://github.com/shakacode/react_on_rails/issues/504
# Nevertheless, here's this working:

express: sh -c 'HOT_PORT=4000 npm start'
27 changes: 19 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ By Justin Gordon and the Shaka Code Team, [www.shakacode.com](http://www.shakaco
An outdated full tutorial article behind of the motivation of this system can be found at: [Fast Rich Client Rails Development With Webpack and the ES6 Transpiler](http://www.railsonmaui.com/blog/2014/10/03/integrating-webpack-and-the-es6-transpiler-into-an-existing-rails-project/). Note, this source code repository is way ahead of the tutorial.

# NEWS
We have not yet updated the `react_on_rails` gem generators for the following tasks. We're looking for help to migrate this, if you're interested in contributing to the project. *The tutorial* refers to this repo. The following changes have resulted in lots of differences for the webpack files and visual assets:
We have not yet updated the `react_on_rails` gem generators for the following tasks, and we probably never will. *The tutorial* refers to this repo. The following changes have resulted in lots of differences for the webpack files and visual assets:

1. NOTE: Any references to localhost:3000 *might* need to use 0.0.0.0:3000 until Puma fixes an issue regarding this.
1. **Handling of Sass and Bootstrap**: The tutorial uses CSS modules via Webpack. This is totally different than the older way of having Rails handle Sass/Bootstrap, and having NPM/Webpack handle the Webpack Dev Server. The tutorial now has NPM handle all visual assets. We are using this technique on a new app, and it's awesome!
Expand Down Expand Up @@ -81,9 +81,6 @@ See package.json and Gemfile for versions
1. `foreman start -f Procfile.hot`
1. Open a browser tab to http://localhost:3000 for the Rails app example with HOT RELOADING
2. Try Hot Reloading steps below!
1. `foreman start -f Procfile.express`
1. Open a browser tab to http://localhost:4000 for the Hot Module Replacement Example just using an express server (no Rails involved). This is good for fast prototyping of React components. However, this setup is not as useful now that we have hot reloading working for Rails!
2. Try Hot Reloading steps below!
1. `foreman start -f Procfile.static`
1. Open a browser tab to http://localhost:3000 for the Rails app example.
2. When you make changes, you have to refresh the browser page.
Expand All @@ -98,7 +95,6 @@ See package.json and Gemfile for versions
1. See all npm commands: `npm run`
1. Start all development processes: `foreman start -f Procfile.dev`
1. Start all Rails only development processes: `foreman start -f Procfile.hot`
1. Start development without Rails, using the Webpack Dev Server only: `npm start` (or `foreman start -f Procfile.express`)


# Javascript development without Rails using the Webpack Dev Server
Expand Down Expand Up @@ -138,7 +134,7 @@ line in the `rails_helper.rb` file. If you are using this project as an example
## Config Files

- `webpack.client.base.config.js`: Common **client** configuration file to minimize code duplication for `webpack.client.rails.build.config`, `webpack.client.rails.hot.config`, `webpack.client.express.config`
- `webpack.client.express.config.js`: Webpack configuration for [client/server-express.js](client/server-express.js)
- `webpack.client.express.config.js`: Webpack configuration for Express server [client/server-express.js](client/server-express.js)
- `webpack.client.rails.build.config.js`: Client side js bundle for deployment and tests.
- `webpack.client.rails.hot.config.js`: Webpack Dev Server bundler for serving rails assets on port 3500, used by [client/server-rails-hot.js](client/server-rails-hot.js), for hot reloading JS and CSS within Rails.
- `webpack.server.rails.build.config.js`: Server side js bundle, used by server rendering.
Expand Down Expand Up @@ -180,11 +176,26 @@ bundle exec foreman start -f <Procfile>
1. [`Procfile.dev`](Procfile.dev): Starts the Webpack Dev Server and Rails with Hot Reloading.
2. [`Procfile.hot`](Procfile.hot): Starts the Rails server and the webpack server to provide hot reloading of assets, JavaScript and CSS.
3. [`Procfile.static`](Procfile.static): Starts the Rails server and generates static assets that are used for tests.
4. [`Procfile.express`](Procfile.express): Starts only the Webpack Dev Server.
5. [`Procfile.spec`](Procfile.spec): Starts webpack to create the static files for tests. **Good to know:** If you want to start `rails s` separately to debug in `pry`, then run `Procfile.spec` to generate the assets and run `rails s` in a separate console.
6. [`Procfile.static.trace`](Procfile.static.trace): Same as `Procfile.static` but prints tracing information useful for debugging server rendering.
4. [`Procfile.express`](Procfile.express): Starts only the Webpack Dev Server for rendering your components with only an Express server.

In general, you want to avoid running more webpack watch processes than you need.

## Rendering With an Express Server
UPDATE: 2016-07-31

We no longer recommend using an express server with Rails. It's simply not necessary because:

1. Rails can hot reload
2. There's extra maintenance in keeping this synchronized.
3. React on Rails does not have a shared_store JS rendering, per [issue #504](https://github.com/shakacode/react_on_rails/issues/504)

### Here's how to run the express server setup

In general, you want to avoid running more webpack watch processes than you need. The `Procfile.dev`, for example, runs both the express server (Webpack dev server) and the Rails hot assets reloading server.
1. `foreman start -f Procfile.express`
2. Open a browser tab to http://localhost:4000 for the Hot Module Replacement Example just using an express server (no Rails involved). This is good for fast prototyping of React components. However, this setup is not as useful now that we have hot reloading working for Rails!
3. Try Hot Reloading steps below!

## Contributors
[The Shaka Code team!](http://www.shakacode.com/about/), led by [Justin Gordon](https://github.com/justin808/), along with with many others. See [contributors.md](docs/contributors.md)
Expand Down
35 changes: 35 additions & 0 deletions client/app/bundles/comments/startup/ClientRouterAppExpress.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Compare to ../ServerRouterApp.jsx
// This
import React from 'react';
import { Provider } from 'react-redux';
import ReactOnRails from 'react-on-rails';
import { Router, browserHistory } from 'react-router';
import routes from '../routes/routes';
import { syncHistoryWithStore } from 'react-router-redux';

// No need for this file if using shared stores, but to make this example work for simple express
// server rendering, we only try get the shared store if the props were not passed.
// See https://github.com/shakacode/react_on_rails/issues/504
import createStore from '../store/routerCommentsStore';

const RouterAppExpress = (_props, _railsContext) => {

// See comment above
const store = createStore(_props);

// Create an enhanced history that syncs navigation events with the store
const history = syncHistoryWithStore(
browserHistory,
store
);

return (
<Provider store={store}>
<Router history={history} children={routes} />
</Provider>
);
};

ReactOnRails.register({
RouterAppExpress,
});
11 changes: 10 additions & 1 deletion client/index.pug
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,14 @@ html

script(src="vendor-bundle.js")
script(src="app-bundle.js")

// Next call is not available.
// https://github.com/shakacode/react_on_rails/issues/504
// script.
// ReactOnRails.reduxStore('routerCommentsStore', !{props});
// script.
// ReactOnRails.render('RouterApp', !{}, 'app');
//
// Instead, we'll pass the props and special case in startup
script.
ReactOnRails.render("RouterApp", !{props}, 'app');
ReactOnRails.render('RouterAppExpress', !{props}, 'app');
4 changes: 2 additions & 2 deletions client/server-express.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ server.app.use(bodyParser.urlencoded({ extended: true }));
server.app.get('/comments.json', (req, res) => {
sleep.sleep(1);
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify(comments));
res.send(JSON.stringify({ comments }));
});

server.app.post('/comments.json', (req, res) => {
Expand All @@ -49,7 +49,7 @@ server.app.post('/comments.json', (req, res) => {

server.app.use('/', (req, res) => {
var locals = {
props: JSON.stringify(comments),
props: JSON.stringify({ comments }),
};
var layout = `${process.cwd()}/index.pug`;
var html = pug.compileFile(layout, { pretty: true })(locals);
Expand Down
4 changes: 4 additions & 0 deletions client/webpack.client.express.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ const hotPort = process.env.HOT_PORT || 4000;
config.entry.vendor.push('bootstrap-loader');
config.entry.app.push(

// Shouldn't be necessary:
// https://github.com/shakacode/react_on_rails/issues/504
'./app/bundles/comments/startup/ClientRouterAppExpress',

// Webpack dev server
`webpack-dev-server/client?http://localhost:${hotPort}`,
'webpack/hot/dev-server'
Expand Down

0 comments on commit 94c72bd

Please sign in to comment.