Skip to content

Commit

Permalink
feat(react): add react fast refresh to webpack (nrwl#5612)
Browse files Browse the repository at this point in the history
  • Loading branch information
xiongemi authored May 18, 2021
1 parent 4a0dcba commit b8584a6
Show file tree
Hide file tree
Showing 18 changed files with 133 additions and 20 deletions.
8 changes: 8 additions & 0 deletions docs/angular/api-web/executors/dev-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ Type: `string`

Target which builds the application

### hmr

Default: `false`

Type: `boolean`

Enable hot module replacement.

### host

Default: `localhost`
Expand Down
8 changes: 4 additions & 4 deletions docs/angular/cli/serve.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ The options below are common to the `serve` command used within an Nx workspace.

This option allows you to whitelist services that are allowed to access the dev server.

### hmr

Enable hot module replacement.

### host

Host to listen on.
Expand Down Expand Up @@ -140,10 +144,6 @@ Don't verify connected clients are part of allowed hosts.

Output in-file eval sourcemaps.

### hmr

Enable hot module replacement.

### hmr-warning

Show a warning when the `--hmr` option is enabled.
Expand Down
8 changes: 8 additions & 0 deletions docs/node/api-web/executors/dev-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ Type: `string`

Target which builds the application

### hmr

Default: `false`

Type: `boolean`

Enable hot module replacement.

### host

Default: `localhost`
Expand Down
8 changes: 4 additions & 4 deletions docs/node/cli/serve.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ The options below are common to the `serve` command used within an Nx workspace.

This option allows you to whitelist services that are allowed to access the dev server.

### hmr

Enable hot module replacement.

### host

Host to listen on.
Expand Down Expand Up @@ -140,10 +144,6 @@ Don't verify connected clients are part of allowed hosts.

Output in-file eval sourcemaps.

### hmr

Enable hot module replacement.

### hmr-warning

Show a warning when the `--hmr` option is enabled.
Expand Down
8 changes: 8 additions & 0 deletions docs/react/api-web/executors/dev-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ Type: `string`

Target which builds the application

### hmr

Default: `false`

Type: `boolean`

Enable hot module replacement.

### host

Default: `localhost`
Expand Down
8 changes: 4 additions & 4 deletions docs/react/cli/serve.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ The options below are common to the `serve` command used within an Nx workspace.

This option allows you to whitelist services that are allowed to access the dev server.

### hmr

Enable hot module replacement.

### host

Host to listen on.
Expand Down Expand Up @@ -140,10 +144,6 @@ Don't verify connected clients are part of allowed hosts.

Output in-file eval sourcemaps.

### hmr

Enable hot module replacement.

### hmr-warning

Show a warning when the `--hmr` option is enabled.
Expand Down
1 change: 1 addition & 0 deletions docs/react/tutorial/06-proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ Options:
--sslCert SSL certificate to use for serving HTTPS.
--watch Watches for changes and rebuilds application (default: true)
--liveReload Whether to reload the page on change, using live-reload. (default: true)
--hmr Enable hot module replacement.
--publicHost Public URL where the application will be served
--open Open the application in the browser.
--allowedHosts This option allows you to whitelist services that are allowed to access the dev server.
Expand Down
8 changes: 4 additions & 4 deletions docs/shared/cli/serve.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ The options below are common to the `serve` command used within an Nx workspace.

This option allows you to whitelist services that are allowed to access the dev server.

### hmr

Enable hot module replacement.

### host

Host to listen on.
Expand Down Expand Up @@ -140,10 +144,6 @@ Don't verify connected clients are part of allowed hosts.

Output in-file eval sourcemaps.

### hmr

Enable hot module replacement.

### hmr-warning

Show a warning when the `--hmr` option is enabled.
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"@nrwl/tao": "12.3.0",
"@nrwl/web": "12.3.0",
"@nrwl/workspace": "12.3.0",
"@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
"@popperjs/core": "^2.9.2",
"@reduxjs/toolkit": "1.5.0",
"@rollup/plugin-babel": "5.0.2",
Expand Down Expand Up @@ -189,6 +190,7 @@
"protractor": "5.4.3",
"raw-loader": "3.1.0",
"react-redux": "7.2.3",
"react-refresh": "^0.9.0",
"react-router-dom": "5.1.2",
"regenerator-runtime": "0.13.7",
"release-it": "^7.4.0",
Expand Down
2 changes: 2 additions & 0 deletions packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@
"@nrwl/storybook": "*",
"@nrwl/web": "*",
"@nrwl/workspace": "*",
"@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
"@svgr/webpack": "^5.4.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.23.1",
"eslint-plugin-react-hooks": "^4.2.0",
"react-refresh": "^0.9.0",
"url-loader": "^3.0.0"
}
}
22 changes: 22 additions & 0 deletions packages/react/plugins/webpack.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Configuration } from 'webpack';
import * as ReactRefreshPlugin from '@pmmmwh/react-refresh-webpack-plugin';

// Add React-specific configuration
function getWebpackConfig(config: Configuration) {
Expand Down Expand Up @@ -54,6 +55,27 @@ function getWebpackConfig(config: Configuration) {
}
);

if (config.mode === 'development' && config['devServer']?.hot) {
// add `react-refresh/babel` to babel loader plugin
const babelLoader = config.module.rules.find((rule) =>
rule.loader.toString().includes('babel-loader')
);
if (babelLoader) {
babelLoader.options['plugins'] = [
...(babelLoader.options['plugins'] || []),
[
require.resolve('react-refresh/babel'),
{
skipEnvCheck: true,
},
],
];
}

// add https://github.com/pmmmwh/react-refresh-webpack-plugin to webpack plugin
config.plugins.push(new ReactRefreshPlugin());
}

return config;
}

Expand Down
2 changes: 2 additions & 0 deletions packages/react/src/generators/application/application.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,9 +278,11 @@ describe('app', () => {
expect(targetConfig.serve.executor).toEqual('@nrwl/web:dev-server');
expect(targetConfig.serve.options).toEqual({
buildTarget: 'my-app:build',
hmr: true,
});
expect(targetConfig.serve.configurations.production).toEqual({
buildTarget: 'my-app:build:production',
hmr: false,
});
});

Expand Down
2 changes: 2 additions & 0 deletions packages/react/src/generators/application/lib/add-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,12 @@ function createServeTarget(options: NormalizedSchema): TargetConfiguration {
executor: '@nrwl/web:dev-server',
options: {
buildTarget: `${options.projectName}:build`,
hmr: true,
},
configurations: {
production: {
buildTarget: `${options.projectName}:build:production`,
hmr: false,
},
},
};
Expand Down
1 change: 1 addition & 0 deletions packages/web/src/builders/dev-server/dev-server.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export interface WebDevServerOptions {
buildTarget: string;
open: boolean;
liveReload: boolean;
hmr: boolean;
watch: boolean;
allowedHosts: string;
maxWorkers?: number;
Expand Down
5 changes: 5 additions & 0 deletions packages/web/src/builders/dev-server/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@
"description": "Whether to reload the page on change, using live-reload.",
"default": true
},
"hmr": {
"type": "boolean",
"description": "Enable hot module replacement.",
"default": false
},
"publicHost": {
"type": "string",
"description": "Public URL where the application will be served"
Expand Down
42 changes: 40 additions & 2 deletions packages/web/src/utils/devserver.config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { getDevServerConfig } from './devserver.config';
import TsConfigPathsPlugin from 'tsconfig-paths-webpack-plugin';
import * as ts from 'typescript';
import * as fs from 'fs';
import { HotModuleReplacementPlugin } from 'webpack';
import { WebBuildBuilderOptions } from '../builders/build/build.impl';
import { WebDevServerOptions } from '../builders/dev-server/dev-server.impl';
import { join } from 'path';
Expand Down Expand Up @@ -54,6 +55,7 @@ describe('getDevServerConfig', () => {
buildTarget: 'webapp:build',
ssl: false,
liveReload: true,
hmr: true,
open: false,
watch: true,
allowedHosts: null,
Expand Down Expand Up @@ -328,7 +330,7 @@ describe('getDevServerConfig', () => {
root,
sourceRoot,
buildInput,
serveInput
{ ...serveInput, hmr: false }
);

expect(result.liveReload).toEqual(true);
Expand All @@ -339,13 +341,49 @@ describe('getDevServerConfig', () => {
root,
sourceRoot,
buildInput,
{ ...serveInput, liveReload: false }
{ ...serveInput, hmr: false, liveReload: false }
);

expect(result.liveReload).toEqual(false);
});
});

describe('hmr option', () => {
it('should set the correct value', () => {
const { devServer: result } = getDevServerConfig(
root,
sourceRoot,
buildInput,
{ ...serveInput, hmr: false }
);

expect(result.hot).toEqual(false);
});

it('should set the correct if true and disable live reload', () => {
const { devServer: result } = getDevServerConfig(
root,
sourceRoot,
buildInput,
serveInput
);

expect(result.liveReload).toEqual(false);
expect(result.hot).toEqual(true);
});

it('should add hot module replacement plugin', () => {
const { plugins } = getDevServerConfig(
root,
sourceRoot,
buildInput,
serveInput
);

expect(plugins).toContainEqual(new HotModuleReplacementPlugin());
});
});

describe('ssl option', () => {
it('should set https to false if not on', () => {
const { devServer: result } = getDevServerConfig(
Expand Down
13 changes: 11 additions & 2 deletions packages/web/src/utils/devserver.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { readFileSync } from 'fs';
import * as path from 'path';

import { getWebConfig } from './web.config';
import { Configuration } from 'webpack';
import { Configuration, HotModuleReplacementPlugin } from 'webpack';
import { WebBuildBuilderOptions } from '../builders/build/build.impl';
import { WebDevServerOptions } from '../builders/dev-server/dev-server.impl';
import { buildServePath } from './serve-path';
Expand All @@ -31,6 +31,10 @@ export function getDevServerConfig(
serveOptions,
buildOptions
);
webpackConfig.plugins = [
...(webpackConfig.plugins || []),
getHmrPlugin(serveOptions),
].filter(Boolean);

return webpackConfig;
}
Expand Down Expand Up @@ -85,7 +89,8 @@ function getDevServerPartial(
publicPath: servePath,
contentBase: false,
allowedHosts: [],
liveReload: options.liveReload,
liveReload: options.hmr ? false : options.liveReload, // disable liveReload if hmr is enabled
hot: options.hmr,
};

if (options.ssl && options.sslKey && options.sslCert) {
Expand Down Expand Up @@ -114,3 +119,7 @@ function getProxyConfig(root: string, options: WebDevServerOptions) {
const proxyPath = path.resolve(root, options.proxyConfig as string);
return require(proxyPath);
}

function getHmrPlugin(options: WebDevServerOptions) {
return options.hmr && new HotModuleReplacementPlugin();
}
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -20519,6 +20519,11 @@ [email protected], react-refresh@^0.8.3:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==

react-refresh@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.9.0.tgz#71863337adc3e5c2f8a6bfddd12ae3bfe32aafbf"
integrity sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ==

[email protected]:
version "5.1.2"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.1.2.tgz#06701b834352f44d37fbb6311f870f84c76b9c18"
Expand Down

0 comments on commit b8584a6

Please sign in to comment.