Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve developer experience; update react-error-overlay #1421

Merged
merged 1 commit into from
Oct 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@
"prettier": "^1.7.3",
"raw-loader": "^0.5.1",
"react-deep-force-update": "^2.1.1",
"react-error-overlay": "^1.0.9",
"react-hot-loader": "^3.0.0-beta.7",
"react-dev-utils": "^4.1.0",
"react-error-overlay": "^2.0.2",
"react-test-renderer": "^16.0.0",
"rimraf": "^2.6.2",
"stylelint": "^8.1.1",
Expand Down
16 changes: 8 additions & 8 deletions src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ import history from './history';
import { updateMeta } from './DOMUtils';
import router from './router';

/* eslint-disable global-require */

// Global (context) variables that can be easily accessed from any React component
// https://facebook.github.io/react/docs/context.html
const context = {
Expand All @@ -40,8 +38,8 @@ const context = {
};

const container = document.getElementById('app');
let appInstance;
let currentLocation = history.location;
let appInstance;

// Switch off the native scroll restoration behavior and handle it manually
// https://developers.google.com/web/updates/2015/09/history-api-scroll-restoration
Expand All @@ -63,6 +61,7 @@ async function onLocationChange(location, action) {
}
currentLocation = location;

const isInitialRender = !action;
try {
// Traverses the list of routes in the order they are defined until
// it finds the first route that matches provided URL path string
Expand All @@ -83,14 +82,15 @@ async function onLocationChange(location, action) {
return;
}

appInstance = ReactDOM[action ? 'render' : 'hydrate'](
const renderReactApp = isInitialRender ? ReactDOM.hydrate : ReactDOM.render;
appInstance = renderReactApp(
<App context={context}>{route.component}</App>,
container,
() => {
if (!action) {
if (isInitialRender) {
const elem = document.getElementById('css');
if (elem) elem.parentNode.removeChild(elem);
return; // Initial render complete
return;
}

document.title = route.title;
Expand Down Expand Up @@ -139,7 +139,7 @@ async function onLocationChange(location, action) {
console.error(error);

// Do a full page reload if error occurs during client-side navigation
if (action && currentLocation.key === location.key) {
if (!isInitialRender && currentLocation.key === location.key) {
window.location.reload();
}
}
Expand All @@ -153,7 +153,7 @@ onLocationChange(currentLocation);
// Enable Hot Module Replacement (HMR)
if (module.hot) {
module.hot.accept('./router', () => {
if (appInstance) {
if (appInstance && appInstance.updater.isMounted(appInstance)) {
// Force-update the whole tree, including components that refuse to update
deepForceUpdate(appInstance);
}
Expand Down
5 changes: 2 additions & 3 deletions tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
* Copies static files to the output folder (`copy.js`)
* Launches [Webpack](https://webpack.github.io/) compiler in a watch mode (via [webpack-middleware](https://github.com/kriasoft/webpack-middleware))
* Launches Node.js server from the compiled output folder (`runServer.js`)
* Launches [Browsersync](https://browsersync.io/),
[Hot Module Replacement](https://webpack.github.io/docs/hot-module-replacement), and
[React Hot Loader](https://github.com/gaearon/react-hot-loader)
* Launches [Browsersync](https://browsersync.io/) and
[Hot Module Replacement](https://webpack.github.io/docs/hot-module-replacement)

### `yarn run build` (`build.js`)

Expand Down
42 changes: 42 additions & 0 deletions tools/lib/webpackHotDevClient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* React Starter Kit (https://www.reactstarterkit.com/)
*
* Copyright © 2014-present 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-next-line import/no-unresolved, import/extensions
import hotClient from 'webpack-hot-middleware/client?name=client&reload=true';
import launchEditorEndpoint from 'react-dev-utils/launchEditorEndpoint';
import formatWebpackMessages from 'react-dev-utils/formatWebpackMessages';
import {
reportBuildError,
dismissBuildError,
startReportingRuntimeErrors,
stopReportingRuntimeErrors,
} from 'react-error-overlay';

hotClient.useCustomOverlay({
showProblems(type, errors) {
const formatted = formatWebpackMessages({
errors,
warnings: [],
});

reportBuildError(formatted.errors[0]);
},
clear() {
dismissBuildError();
},
});

startReportingRuntimeErrors({
launchEditorEndpoint,
filename: '/assets/client.js',
});

if (module.hot) {
module.hot.dispose(stopReportingRuntimeErrors);
}
14 changes: 3 additions & 11 deletions tools/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import browserSync from 'browser-sync';
import webpack from 'webpack';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import createLaunchEditorMiddleware from 'react-error-overlay/middleware';
import errorOverlayMiddleware from 'react-dev-utils/errorOverlayMiddleware';
import webpackConfig from './webpack.config';
import run, { format } from './run';
import clean from './clean';
Expand Down Expand Up @@ -66,16 +66,12 @@ let server;
async function start() {
if (server) return server;
server = express();
server.use(createLaunchEditorMiddleware());
server.use(errorOverlayMiddleware());
server.use(express.static(path.resolve(__dirname, '../public')));

// Configure client-side hot module replacement
const clientConfig = webpackConfig.find(config => config.name === 'client');
clientConfig.entry.client = [
'react-error-overlay',
'react-hot-loader/patch',
'webpack-hot-middleware/client?name=client&reload=true',
]
clientConfig.entry.client = ['./tools/lib/webpackHotDevClient']
.concat(clientConfig.entry.client)
.sort((a, b) => b.includes('polyfill') - a.includes('polyfill'));
clientConfig.output.filename = clientConfig.output.filename.replace(
Expand All @@ -89,10 +85,6 @@ async function start() {
clientConfig.module.rules = clientConfig.module.rules.filter(
x => x.loader !== 'null-loader',
);
const { options } = clientConfig.module.rules.find(
x => x.loader === 'babel-loader',
);
options.plugins = ['react-hot-loader/babel'].concat(options.plugins || []);
clientConfig.plugins.push(
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
Expand Down
Loading