diff --git a/CHANGELOG.md b/CHANGELOG.md index 69957b9aa..c18b4c1b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,10 @@ All notable changes to this project will be documented in this file. Items under Contributors: please follow the recommendations outlined at [keepachangelog.com](http://keepachangelog.com/). Please use the existing headings and styling as a guide, and add a link for the version diff at the bottom of the file. Also, please update the `Unreleased` link to compare to the latest release version. ## [Unreleased] + +## [6.2.0] ##### Added -- New API registerRenderer which allows a user to manually render their app to the DOM by [jtibbertsma](https://github.com/jtibbertsma) +- New API registerRenderer which allows a user to manually render their app to the DOM [#581](https://github.com/shakacode/react_on_rails/pull/581) by [jtibbertsma](https://github.com/jtibbertsma). ## [6.1.2] 2016-10-24 ##### Fixed @@ -376,7 +378,8 @@ Best done with Object destructing: ##### Fixed - Fix several generator related issues. -[Unreleased]: https://github.com/shakacode/react_on_rails/compare/6.1.2...master +[Unreleased]: https://github.com/shakacode/react_on_rails/compare/6.2.0...master +[6.2.0]: https://github.com/shakacode/react_on_rails/compare/6.1.2...6.2.0 [6.1.2]: https://github.com/shakacode/react_on_rails/compare/6.1.1...6.1.2 [6.1.1]: https://github.com/shakacode/react_on_rails/compare/6.1.0...6.1.1 [6.1.0]: https://github.com/shakacode/react_on_rails/compare/6.0.5...6.1.0 diff --git a/README.md b/README.md index cb4837c61..1b13f390b 100644 --- a/README.md +++ b/README.md @@ -454,6 +454,7 @@ If you are using [jquery-ujs](https://github.com/rails/jquery-ujs) for AJAX call 1. [React on Rails docs for react-router](docs/additional-reading/react-router.md) 1. Examples in [spec/dummy/app/views/react_router](spec/dummy/app/views/react_router) and follow to the JavaScript code in the [spec/dummy/client/app/startup/ServerRouterApp.jsx](spec/dummy/client/app/startup/ServerRouterApp.jsx). +1. [Code Splitting docs](docs/additional-reading/code-splitting.md) for information about how to set up code splitting for server rendered routes. ## Deployment * Version 6.0 puts the necessary precompile steps automatically in the rake precompile step. You can, however, disable this by setting certain values to nil in the [config/initializers/react_on_rails.rb](spec/dummy/config/initializers/react_on_rails.rb). @@ -484,6 +485,7 @@ Node.js can be used as the backend for server-side rendering instead of [execJS] + [Developing with the Webpack Dev Server](docs/additional-reading/webpack-dev-server.md) + [Node Server Rendering](docs/additional-reading/node-server-rendering.md) + [Server Rendering Tips](docs/additional-reading/server-rendering-tips.md) + + [Code Splitting](docs/additional-reading/code-splitting.md) + **Development** + [React on Rails Basic Installation Tutorial](docs/tutorial.md) ([live demo](https://hello-react-on-rails.herokuapp.com)) diff --git a/docs/additional-reading/code-splitting.md b/docs/additional-reading/code-splitting.md index b4df68708..35b11fe06 100644 --- a/docs/additional-reading/code-splitting.md +++ b/docs/additional-reading/code-splitting.md @@ -8,11 +8,11 @@ What is code splitting? From the webpack documentation: Let's say you're requesting a page that needs to fetch a code chunk from the server before it's able to render. If you do all your rendering on the client side, you don't have to do anything special. However, if the page is rendered on the server, you'll find that React will spit out the following error: -``` -Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server: - (client) Different markup is generated on the client than on the server. Why does this happen? When you register a component with `ReactOnRails.register`, react on rails will render the component as soon as the page loads. However, react-router renders a comment while waiting for the code chunk to be fetched from the server. This means that react will tear all of the server rendered code out of the DOM, and then rerender it a moment later once the code chunk arrives from the server, defeating most of the purpose of server rendering. @@ -23,14 +23,14 @@ To prevent this, you have to wait until the code chunk is fetched before doing t Here's an example of how you might use this in practice: -page.html.erb +#### page.html.erb ```erb <%= redux_store_hydration_data %> <%= react_component("NavigationApp", prerender: true) %> <%= react_component("RouterApp", prerender: true) %> ``` -clientRegistration.js +#### clientRegistration.js ```js import ReactOnRails from 'react-on-rails'; import NavigationApp from './NavigationApp'; @@ -42,7 +42,22 @@ ReactOnRails.register({NavigationApp}); ReactOnRails.registerRenderer({RouterApp}); ``` -RouterAppRenderer.jsx +#### serverRegistration.js +```js +import ReactOnRails from 'react-on-rails'; +import NavigationApp from './NavigationApp'; +import RouterApp from './RouterAppServer'; +import applicationStore from '../store/applicationStore'; + +ReactOnRails.registerStore({applicationStore}); +ReactOnRails.register({ + NavigationApp, + RouterApp, +}); +``` +Note that you should not use `registerRenderer` on the server. Instead, use `register` like normal. For an example of how to set up an app for server rendering, see the [react router docs](react-router.md). + +#### RouterAppRenderer.jsx ```jsx import ReactOnRails from 'react-on-rails'; import React from 'react'; @@ -82,7 +97,7 @@ Note that in page.html.erb, we call `react_component` in the exact same way as i ### Caveats -If you're going to try to do code splitting with server rendered routes, it's important that you have seperate webpack configurations for client and server. The code splitting happens for the client, but the server should one big file. +If you're going to try to do code splitting with server rendered routes, you'll probably need to use seperate route definitions for client and server to prevent code splitting from happening for the server bundle. The server bundle should be one file containing all the JavaScript code. The reason is we do server rendering with ExecJS, which is not capable of doing anything asynchronous. See [this issue](https://github.com/shakacode/react_on_rails/issues/477) for a discussion. diff --git a/docs/api/javascript-api.md b/docs/api/javascript-api.md index 4eeff8e01..ab606b884 100644 --- a/docs/api/javascript-api.md +++ b/docs/api/javascript-api.md @@ -17,6 +17,15 @@ The best source of docs is the main [ReactOnRails.js](../../node_package/src/Rea */ registerStore(stores) + /** + * Allows registration of renderers. A renderer is a function that accept three args: + * props, railsContext, and domNodeId, and is responsible for rendering a component + * to the DOM. Not available on the server. For one possible use case see: +https://github.com/shakacode/react_on_rails/blob/master/docs/additional-reading/code-splitting.md + * @param renderers (key is component name, value is renderer) + */ + registerRenderer(renderers) + /** * Allows retrieval of the store by name. This store will be hydrated by any Rails form props. * Pass optional param throwIfMissing = false if you want to use this call to get back null if the @@ -57,13 +66,4 @@ The best source of docs is the main [ReactOnRails.js](../../node_package/src/Rea */ authenticityHeaders(otherHeaders = {}) - - /** - * Allows registration of renderers. A renderer is a function that accept three args: - * props, railsContext, and domNodeId, and is responsible for rendering a component - * to the DOM. Not available on the server. For one possible use case see: -https://github.com/shakacode/react_on_rails/blob/master/docs/additional-reading/code-splitting.md - * @param renderers (key is component name, value is renderer) - */ - registerRenderer(renderers) ``` diff --git a/node_package/src/ReactOnRails.js b/node_package/src/ReactOnRails.js index cc73fafe2..5089170f2 100644 --- a/node_package/src/ReactOnRails.js +++ b/node_package/src/ReactOnRails.js @@ -41,6 +41,17 @@ ctx.ReactOnRails = { StoreRegistry.register(stores); }, + /** + * Allows registration of renderers. A renderer is a function that accept three args: + * props, railsContext, and domNodeId, and is responsible for rendering a component + * to the DOM. Not available on the server. For one possible use case see: +https://github.com/shakacode/react_on_rails/blob/master/docs/additional-reading/code-splitting.md + * @param renderers (key is component name, value is renderer) + */ + registerRenderer(renderers) { + ComponentRegistry.registerRenderer(renderers); + }, + /** * Allows retrieval of the store by name. This store will be hydrated by any Rails form props. * Pass optional param throwIfMissing = false if you want to use this call to get back null if the @@ -101,17 +112,6 @@ ctx.ReactOnRails = { return Authenticity.authenticityHeaders(otherHeaders); }, - /** - * Allows registration of renderers. A renderer is a function that accept three args: - * props, railsContext, and domNodeId, and is responsible for rendering a component - * to the DOM. Not available on the server. For one possible use case see: -https://github.com/shakacode/react_on_rails/blob/master/docs/additional-reading/code-splitting.md - * @param renderers (key is component name, value is renderer) - */ - registerRenderer(renderers) { - ComponentRegistry.registerRenderer(renderers); - }, - // ///////////////////////////////////////////////////////////////////////////// // INTERNALLY USED APIs // /////////////////////////////////////////////////////////////////////////////