From 1980b14f3b5e5a2ce886db729f0c2cbe0b772f9f Mon Sep 17 00:00:00 2001 From: Sebastian Sebbie Silbermann Date: Tue, 16 Sep 2025 21:58:58 +0200 Subject: [PATCH 1/4] [DevTools] Don't inline parse Hook name worker --- packages/react-devtools-core/webpack.standalone.js | 2 +- packages/react-devtools-extensions/webpack.config.js | 2 +- packages/react-devtools-fusebox/webpack.config.frontend.js | 2 +- packages/react-devtools-inline/webpack.config.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react-devtools-core/webpack.standalone.js b/packages/react-devtools-core/webpack.standalone.js index 6a9636c6911b1..ca598c3e21c61 100644 --- a/packages/react-devtools-core/webpack.standalone.js +++ b/packages/react-devtools-core/webpack.standalone.js @@ -108,7 +108,7 @@ module.exports = { { loader: 'workerize-loader', options: { - inline: true, + inline: false, name: '[name]', }, }, diff --git a/packages/react-devtools-extensions/webpack.config.js b/packages/react-devtools-extensions/webpack.config.js index 5c03d85dd9315..4592363c64a91 100644 --- a/packages/react-devtools-extensions/webpack.config.js +++ b/packages/react-devtools-extensions/webpack.config.js @@ -261,7 +261,7 @@ module.exports = { { loader: 'workerize-loader', options: { - inline: true, + inline: false, name: '[name]', }, }, diff --git a/packages/react-devtools-fusebox/webpack.config.frontend.js b/packages/react-devtools-fusebox/webpack.config.frontend.js index 1266d3d82895e..a304036a6fa17 100644 --- a/packages/react-devtools-fusebox/webpack.config.frontend.js +++ b/packages/react-devtools-fusebox/webpack.config.frontend.js @@ -101,7 +101,7 @@ module.exports = { { loader: 'workerize-loader', options: { - inline: true, + inline: false, name: '[name]', }, }, diff --git a/packages/react-devtools-inline/webpack.config.js b/packages/react-devtools-inline/webpack.config.js index 358a18f0e7d49..55272cd7a6575 100644 --- a/packages/react-devtools-inline/webpack.config.js +++ b/packages/react-devtools-inline/webpack.config.js @@ -93,7 +93,7 @@ module.exports = { { loader: 'workerize-loader', options: { - inline: true, + inline: false, name: '[name]', }, }, From 55d68fa97114d38643658f297f8d6c3a588a7477 Mon Sep 17 00:00:00 2001 From: Sebastian Sebbie Silbermann Date: Wed, 17 Sep 2025 13:09:28 +0200 Subject: [PATCH 2/4] [DevTools] Persist Playwright test report as CI artifact --- .../workflows/devtools_regression_tests.yml | 2 +- .github/workflows/runtime_build_and_test.yml | 6 +++++ .gitignore | 1 + scripts/ci/run_devtools_e2e_tests.js | 24 ++++++++++++------- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/.github/workflows/devtools_regression_tests.yml b/.github/workflows/devtools_regression_tests.yml index 13b37f1743b45..9fe0c55e0bd00 100644 --- a/.github/workflows/devtools_regression_tests.yml +++ b/.github/workflows/devtools_regression_tests.yml @@ -201,5 +201,5 @@ jobs: - uses: actions/upload-artifact@v4 with: name: screenshots - path: ./tmp/screenshots + path: ./tmp/playwright-artifacts if-no-files-found: warn diff --git a/.github/workflows/runtime_build_and_test.yml b/.github/workflows/runtime_build_and_test.yml index 8ecb956e6b9c6..47293204ac390 100644 --- a/.github/workflows/runtime_build_and_test.yml +++ b/.github/workflows/runtime_build_and_test.yml @@ -831,6 +831,12 @@ jobs: - run: ./scripts/ci/run_devtools_e2e_tests.js env: RELEASE_CHANNEL: experimental + - name: Archive Playwright report + uses: actions/upload-artifact@v4 + with: + name: devtools-playwright-artifacts + path: tmp/playwright-artifacts + if-no-files-found: warn # ----- SIZEBOT ----- sizebot: diff --git a/.gitignore b/.gitignore index 6432df4f054d8..d2aefb620263b 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ chrome-user-data .vscode *.swp *.swo +/tmp packages/react-devtools-core/dist packages/react-devtools-extensions/chrome/build diff --git a/scripts/ci/run_devtools_e2e_tests.js b/scripts/ci/run_devtools_e2e_tests.js index 0d54e710b4d87..040af722ad9a4 100755 --- a/scripts/ci/run_devtools_e2e_tests.js +++ b/scripts/ci/run_devtools_e2e_tests.js @@ -9,7 +9,7 @@ const ROOT_PATH = join(__dirname, '..', '..'); const reactVersion = process.argv[2]; const inlinePackagePath = join(ROOT_PATH, 'packages', 'react-devtools-inline'); const shellPackagePath = join(ROOT_PATH, 'packages', 'react-devtools-shell'); -const screenshotPath = join(ROOT_PATH, 'tmp', 'screenshots'); +const playwrightArtifactsPath = join(ROOT_PATH, 'tmp', 'playwright-artifacts'); const {SUCCESSFUL_COMPILATION_MESSAGE} = require( join(shellPackagePath, 'constants.js') @@ -125,14 +125,22 @@ function runTestShell() { async function runEndToEndTests() { logBright('Running e2e tests'); if (!reactVersion) { - testProcess = spawn('yarn', ['test:e2e', `--output=${screenshotPath}`], { - cwd: inlinePackagePath, - }); + testProcess = spawn( + 'yarn', + ['test:e2e', `--output=${playwrightArtifactsPath}`], + { + cwd: inlinePackagePath, + } + ); } else { - testProcess = spawn('yarn', ['test:e2e', `--output=${screenshotPath}`], { - cwd: inlinePackagePath, - env: {...process.env, REACT_VERSION: reactVersion}, - }); + testProcess = spawn( + 'yarn', + ['test:e2e', `--output=${playwrightArtifactsPath}`], + { + cwd: inlinePackagePath, + env: {...process.env, REACT_VERSION: reactVersion}, + } + ); } testProcess.stdout.on('data', data => { From 820a831c18511c316c749eccd443d4b123a5bf83 Mon Sep 17 00:00:00 2001 From: Sebastian Sebbie Silbermann Date: Wed, 17 Sep 2025 13:48:24 +0200 Subject: [PATCH 3/4] Only outline for extensions --- packages/react-devtools-core/webpack.standalone.js | 3 ++- packages/react-devtools-fusebox/webpack.config.frontend.js | 3 ++- packages/react-devtools-inline/webpack.config.js | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/react-devtools-core/webpack.standalone.js b/packages/react-devtools-core/webpack.standalone.js index ca598c3e21c61..6279ba7fb3498 100644 --- a/packages/react-devtools-core/webpack.standalone.js +++ b/packages/react-devtools-core/webpack.standalone.js @@ -108,7 +108,8 @@ module.exports = { { loader: 'workerize-loader', options: { - inline: false, + // Workers would have to be exposed on a public path in order to outline them. + inline: true, name: '[name]', }, }, diff --git a/packages/react-devtools-fusebox/webpack.config.frontend.js b/packages/react-devtools-fusebox/webpack.config.frontend.js index a304036a6fa17..0d56e81a34b6a 100644 --- a/packages/react-devtools-fusebox/webpack.config.frontend.js +++ b/packages/react-devtools-fusebox/webpack.config.frontend.js @@ -101,7 +101,8 @@ module.exports = { { loader: 'workerize-loader', options: { - inline: false, + // Workers would have to be exposed on a public path in order to outline them. + inline: true, name: '[name]', }, }, diff --git a/packages/react-devtools-inline/webpack.config.js b/packages/react-devtools-inline/webpack.config.js index 55272cd7a6575..a0300069bfa2e 100644 --- a/packages/react-devtools-inline/webpack.config.js +++ b/packages/react-devtools-inline/webpack.config.js @@ -93,7 +93,8 @@ module.exports = { { loader: 'workerize-loader', options: { - inline: false, + // Workers would have to be exposed on a public path in order to outline them. + inline: true, name: '[name]', }, }, From 74a26e044c1da666bc6e5053f8e6c5e9a66b320f Mon Sep 17 00:00:00 2001 From: Sebastian Sebbie Silbermann Date: Wed, 17 Sep 2025 14:49:50 +0200 Subject: [PATCH 4/4] Reduce waterfall by inlining the async chunk --- .../react-devtools-extensions/src/main/index.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/react-devtools-extensions/src/main/index.js b/packages/react-devtools-extensions/src/main/index.js index 362793e3eb430..cec9fd6df454f 100644 --- a/packages/react-devtools-extensions/src/main/index.js +++ b/packages/react-devtools-extensions/src/main/index.js @@ -24,6 +24,7 @@ import { normalizeUrlIfValid, } from 'react-devtools-shared/src/utils'; import {checkConditions} from 'react-devtools-shared/src/devtools/views/Editor/utils'; +import * as parseHookNames from 'react-devtools-shared/src/hooks/parseHookNames'; import { setBrowserSelectionFromReact, @@ -40,6 +41,12 @@ import getProfilingFlags from './getProfilingFlags'; import debounce from './debounce'; import './requestAnimationFramePolyfill'; +const resolvedParseHookNames = Promise.resolve(parseHookNames); +// DevTools assumes this is a dynamically imported module. Since we outline +// workers in this bundle, we can sync require the module since it's just a thin +// wrapper around calling the worker. +const hookNamesModuleLoaderFunction = () => resolvedParseHookNames; + function createBridge() { bridge = new Bridge({ listen(fn) { @@ -188,12 +195,6 @@ function createBridgeAndStore() { ); }; - // TODO (Webpack 5) Hopefully we can remove this prop after the Webpack 5 migration. - const hookNamesModuleLoaderFunction = () => - import( - /* webpackChunkName: 'parseHookNames' */ 'react-devtools-shared/src/hooks/parseHookNames' - ); - root = createRoot(document.createElement('div')); render = (overrideTab = mostRecentOverrideTab) => {