ff-stream-web

git clone git://archive.git.mtrnord.blog/MTRNord/ff-stream-web.git
Log | Files | Refs | README | LICENSE

commit e6e4ca7b06e0e85dec75e53f02ccbb819b996f2a
parent db08f54fb907b047d6ed163419fd00a60a456582
Author: Vladimir Kutepov <frenzzy.man@gmail.com>
Date:   Thu,  3 Nov 2016 02:43:58 +0400

Improve Hot Updates (#938)

Improve Hot Updates

- Add support for hot update of [`PureComponent`](https://facebook.github.io/react/docs/react-api.html#react.purecomponent) and components with [`shouldComponentUpdate`](https://facebook.github.io/react/docs/react-component.html#shouldcomponentupdate)
- Display application errors at full-screen in development mode
- Display hot update errors at full-screen when hot module replacement is enabled

closes #932, #929, #907, #871, #772, #436
Diffstat:
Mpackage.json | 1+
Msrc/client.js | 32++++++++++++++++++++++++++++----
Asrc/core/devUtils.js | 22++++++++++++++++++++++
Msrc/core/history.js | 9+++++++++
4 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/package.json b/package.json @@ -94,6 +94,7 @@ "postcss-url": "^5.1.2", "raw-loader": "^0.5.1", "react-addons-test-utils": "15.3.2", + "react-deep-force-update": "^2.0.1", "react-hot-loader": "^3.0.0-beta.6", "redbox-react": "^1.3.2", "rimraf": "^2.5.4", diff --git a/src/client.js b/src/client.js @@ -16,6 +16,7 @@ import queryString from 'query-string'; import { createPath } from 'history/PathUtils'; import history from './core/history'; import App from './components/App'; +import { ErrorReporter, deepForceUpdate } from './core/devUtils'; // Global (context) variables that can be easily accessed from any React component // https://facebook.github.io/react/docs/context.html @@ -108,6 +109,7 @@ let onRenderComplete = function initialRenderComplete() { FastClick.attach(document.body); const container = document.getElementById('app'); +let appInstance; let currentLocation = history.location; let routes = require('./routes').default; @@ -143,18 +145,28 @@ async function onLocationChange(location) { return; } - ReactDOM.render( + appInstance = ReactDOM.render( <App context={context}>{route.component}</App>, container, () => onRenderComplete(route, location) ); - } catch (err) { + } catch (error) { + console.error(error); // eslint-disable-line no-console + + // Current url has been changed during navigation process, do nothing + if (currentLocation.key !== location.key) { + return; + } + + // Display the error in full-screen for development mode if (process.env.NODE_ENV !== 'production') { - throw err; + appInstance = null; + document.title = `Error: ${error.message}`; + ReactDOM.render(<ErrorReporter error={error} />, container); + return; } // Avoid broken navigation in production mode by a full page reload on error - console.error(err); // eslint-disable-line no-console window.location.reload(); } } @@ -169,6 +181,18 @@ if (module.hot) { module.hot.accept('./routes', () => { routes = require('./routes').default; // eslint-disable-line global-require + if (appInstance) { + try { + // Force-update the whole tree, including components that refuse to update + deepForceUpdate(appInstance); + } catch (error) { + appInstance = null; + document.title = `Hot Update Error: ${error.message}`; + ReactDOM.render(<ErrorReporter error={error} />, container); + return; + } + } + onLocationChange(currentLocation); }); } diff --git a/src/core/devUtils.js b/src/core/devUtils.js @@ -0,0 +1,22 @@ +/** + * React Starter Kit (https://www.reactstarterkit.com/) + * + * Copyright © 2014-2016 Kriasoft, LLC. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE.txt file in the root directory of this source tree. + */ + +/* eslint-disable global-require */ + +if (module.hot || process.env.NODE_ENV !== 'production') { + module.exports = { + // The red box (aka red screen of death) component to display your errors + // https://github.com/commissure/redbox-react + ErrorReporter: require('redbox-react').default, + + // Force-updates React component tree recursively + // https://github.com/gaearon/react-deep-force-update + deepForceUpdate: require('react-deep-force-update'), + }; +} diff --git a/src/core/history.js b/src/core/history.js @@ -1,3 +1,12 @@ +/** + * React Starter Kit (https://www.reactstarterkit.com/) + * + * Copyright © 2014-2016 Kriasoft, LLC. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE.txt file in the root directory of this source tree. + */ + import createBrowserHistory from 'history/createBrowserHistory'; // Navigation manager, e.g. history.push('/home')