Skip to content

Commit ce9252e

Browse files
authored
Add React fast refresh to Sandbox and Playground (#16860)
This change enables React fast refresh in both Sandbox and Playground. This means when changes are made to React components in .tsx files (as long as the React components are exported), the changes will be reflected "immediately" (within about 5 seconds or so).
1 parent b3264e2 commit ce9252e

File tree

7 files changed

+58
-20
lines changed

7 files changed

+58
-20
lines changed

package-lock.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/dev/buildTools/src/webpackTools.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import type { BuildType, DevPackageName, UMDPackageName } from "./packageMapping
55
import { getPackageMappingByDevName, getPublicPackageName, isValidDevPackageName, umdPackageMapping } from "./packageMapping.js";
66
import * as path from "path";
77
import { camelize, copyFile } from "./utils.js";
8-
import type { RuleSetRule, Configuration, Compiler } from "webpack";
8+
import type { RuleSetRule, Configuration, Compiler, WebpackPluginInstance } from "webpack";
9+
import * as ReactRefreshWebpackPlugin from "@pmmmwh/react-refresh-webpack-plugin";
10+
import ReactRefreshTypeScript from "react-refresh-typescript";
911

1012
// eslint-disable-next-line @typescript-eslint/naming-convention
1113
export const externalsFunction = (excludePackages: string[] = [], type: BuildType = "umd") => {
@@ -65,12 +67,22 @@ export const getRules = (
6567
resourceType?: "asset/inline" | "asset/resource";
6668
extraRules?: RuleSetRule[];
6769
mode?: "development" | "production";
70+
enableFastRefresh?: boolean; // for react fast refresh
6871
} = {
6972
includeAssets: true,
7073
includeCSS: true,
7174
sideEffects: true,
7275
}
7376
) => {
77+
const getCustomTransformers = options.enableFastRefresh
78+
? (program: ts.Program) => {
79+
const transformers: ts.CustomTransformers = options?.tsOptions?.getCustomTransformers?.(program) ?? {};
80+
transformers.before = transformers.before ?? [];
81+
transformers.before.push(ReactRefreshTypeScript());
82+
return transformers;
83+
}
84+
: options?.tsOptions?.getCustomTransformers;
85+
7486
const rules: RuleSetRule[] = [
7587
{
7688
test: /\.tsx?$/,
@@ -79,7 +91,7 @@ export const getRules = (
7991
sideEffects: options.sideEffects,
8092
options: {
8193
configFile: "tsconfig.build.json",
82-
...options.tsOptions,
94+
...{ ...options.tsOptions, getCustomTransformers },
8395
},
8496
},
8597
{
@@ -177,9 +189,18 @@ export const commonDevWebpackConfiguration = (
177189
port: number;
178190
static?: string[];
179191
showBuildProgress?: boolean;
180-
}
192+
},
193+
additionalPlugins?: WebpackPluginInstance[]
181194
) => {
182195
const production = env.mode === "production" || process.env.NODE_ENV === "production";
196+
const enableHotReload = (env.enableHotReload !== undefined || process.env.ENABLE_HOT_RELOAD === "true") && !production ? true : false;
197+
198+
let plugins: WebpackPluginInstance[] | undefined = additionalPlugins;
199+
if (devServerConfig && enableHotReload) {
200+
plugins = plugins ?? [];
201+
plugins.push(new ReactRefreshWebpackPlugin());
202+
}
203+
183204
return {
184205
mode: production ? "production" : "development",
185206
devtool: production ? "source-map" : "inline-cheap-module-source-map",
@@ -190,7 +211,7 @@ export const commonDevWebpackConfiguration = (
190211
webSocketServer: production ? false : "ws",
191212
compress: production,
192213
server: env.enableHttps !== undefined || process.env.ENABLE_HTTPS === "true" ? "https" : "http",
193-
hot: (env.enableHotReload !== undefined || process.env.ENABLE_HOT_RELOAD === "true") && !production ? true : false,
214+
hot: enableHotReload,
194215
liveReload: (env.enableLiveReload !== undefined || process.env.ENABLE_LIVE_RELOAD === "true") && !production ? true : false,
195216
headers: {
196217
// eslint-disable-next-line @typescript-eslint/naming-convention
@@ -217,6 +238,7 @@ export const commonDevWebpackConfiguration = (
217238
devtoolModuleFilenameTemplate: production ? "webpack://[namespace]/[resource-path]?[loaders]" : "file:///[absolute-resource-path]",
218239
}
219240
: undefined,
241+
plugins,
220242
};
221243
};
222244

packages/dev/inspector-v2/webpack.config.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
const path = require("path");
22
const webpackTools = require("@dev/build-tools").webpackTools;
3-
const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
4-
const ReactRefreshTypeScript = require("react-refresh-typescript").default;
53

64
module.exports = (env) => {
5+
const production = env.mode === "production" || process.env.NODE_ENV === "production";
76
return {
87
entry: "./test/app/index.ts",
98

@@ -36,16 +35,12 @@ module.exports = (env) => {
3635
rules: webpackTools.getRules({
3736
sideEffects: true,
3837
includeCSS: false,
38+
enableFastRefresh: !production,
3939
tsOptions: {
4040
configFile: "tsconfig.build.json",
41-
getCustomTransformers: () => ({
42-
before: [ReactRefreshTypeScript()].filter(Boolean),
43-
}),
4441
transpileOnly: true,
4542
},
4643
}),
4744
},
48-
49-
plugins: [new ReactRefreshWebpackPlugin()].filter(Boolean),
5045
};
5146
};

packages/tools/playground/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"devDependencies": {
1616
"@dev/build-tools": "1.0.0",
1717
"@dev/core": "1.0.0",
18+
"@pmmmwh/react-refresh-webpack-plugin": "^0.6.0",
1819
"@svgr/webpack": "^7.0.0",
1920
"@types/react": "^18.0.0",
2021
"@types/react-dom": "^18.0.0",
@@ -27,6 +28,8 @@
2728
"monaco-editor-webpack-plugin": "^4.2.0",
2829
"react": "^18.2.0",
2930
"react-dom": "^18.2.0",
31+
"react-refresh": "^0.17.0",
32+
"react-refresh-typescript": "^2.0.10",
3033
"sass-loader": "^16.0.0",
3134
"style-loader": "^3.3.0",
3235
"ts-debounce": "4.0.0",

packages/tools/playground/webpack.config.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,26 @@ const webpackTools = require("@dev/build-tools").webpackTools;
33
const path = require("path");
44

55
module.exports = (env) => {
6+
const production = env.mode === "production" || process.env.NODE_ENV === "production";
67
const commonConfig = {
78
entry: "./src/legacy/legacy.ts",
89
...webpackTools.commonDevWebpackConfiguration(
910
{
1011
...env,
1112
outputFilename: "babylon.playground.js",
1213
dirName: __dirname,
14+
enableHotReload: true,
1315
},
1416
{
1517
static: ["public"],
1618
port: process.env.PLAYGROUND_PORT || 1338,
17-
}
19+
},
20+
[
21+
new MonacoWebpackPlugin({
22+
// publicPath: "public/",
23+
languages: ["typescript", "javascript"],
24+
}),
25+
]
1826
),
1927
resolve: {
2028
extensions: [".js", ".ts", ".tsx", ".scss", "*.svg"],
@@ -71,14 +79,9 @@ module.exports = (env) => {
7179
rootDir: "../../",
7280
},
7381
},
82+
enableFastRefresh: !production,
7483
}),
7584
},
76-
plugins: [
77-
new MonacoWebpackPlugin({
78-
// publicPath: "public/",
79-
languages: ["typescript", "javascript"],
80-
}),
81-
],
8285
};
8386
return commonConfig;
8487
};

packages/tools/sandbox/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"@dev/core": "1.0.0",
3030
"@dev/loaders": "1.0.0",
3131
"@dev/inspector-v2": "1.0.0",
32+
"@pmmmwh/react-refresh-webpack-plugin": "^0.6.0",
3233
"@svgr/webpack": "^7.0.0",
3334
"@types/dagre": "^0.7.47",
3435
"@types/react": "^18.0.0",
@@ -38,6 +39,8 @@
3839
"file-loader": "^6.2.0",
3940
"html-webpack-plugin": "^5.4.0",
4041
"mini-css-extract-plugin": "^2.4.3",
42+
"react-refresh": "^0.17.0",
43+
"react-refresh-typescript": "^2.0.10",
4144
"sass-loader": "^16.0.0",
4245
"style-loader": "^3.3.0",
4346
"url-loader": "^4.1.1",

packages/tools/sandbox/webpack.config.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ const path = require("path");
22
const webpackTools = require("@dev/build-tools").webpackTools;
33

44
module.exports = (env) => {
5+
const production = env.mode === "production" || process.env.NODE_ENV === "production";
56
const commonConfig = {
67
entry: "./src/legacy/legacy.ts",
78
...webpackTools.commonDevWebpackConfiguration(
89
{
910
...env,
1011
outputFilename: "babylon.sandbox.js",
1112
dirName: __dirname,
13+
enableHotReload: true,
1214
},
1315
{
1416
static: ["public"],
@@ -50,9 +52,13 @@ module.exports = (env) => {
5052
// React, react dom etc'
5153
],
5254
module: {
53-
rules: webpackTools.getRules(),
55+
rules: webpackTools.getRules({
56+
includeAssets: true,
57+
includeCSS: true,
58+
sideEffects: true,
59+
enableFastRefresh: !production,
60+
}),
5461
},
55-
plugins: [],
5662
};
5763
return commonConfig;
5864
};

0 commit comments

Comments
 (0)