Skip to content

Commit 3782244

Browse files
authored
feat(core): Add bundler tracing/profiling (#11006)
* Add rspack tracing/profiling * Add CLI start PerfLogger * cleanup BundlerCPUProfilerPlugin
1 parent e88f1aa commit 3782244

File tree

6 files changed

+80
-6
lines changed

6 files changed

+80
-6
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,6 @@ website/i18n/**/*
4545
#!website/i18n/fr/**/*
4646

4747
.netlify
48+
49+
website/rspack-tracing.json
50+
website/bundler-cpu-profile.json

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@
1515
"scripts": {
1616
"start": "yarn build:packages && yarn start:website",
1717
"start:website": "yarn workspace website start",
18+
"start:website:profile": "DOCUSAURUS_BUNDLER_CPU_PROFILE=true DOCUSAURUS_RSPACK_TRACE=true yarn workspace website start",
1819
"start:website:baseUrl": "yarn workspace website start:baseUrl",
1920
"start:website:blogOnly": "yarn workspace website start:blogOnly",
2021
"start:website:deployPreview": "cross-env NETLIFY=true CONTEXT='deploy-preview' yarn workspace website start",
2122
"examples:generate": "node admin/scripts/generateExamples.js",
2223
"build": "yarn build:packages && yarn build:website",
2324
"build:packages": "lerna run build --no-private",
2425
"build:website": "yarn workspace website build",
26+
"build:website:profile": "DOCUSAURUS_BUNDLER_CPU_PROFILE=true DOCUSAURUS_RSPACK_TRACE=true yarn workspace website build",
2527
"build:website:baseUrl": "yarn workspace website build:baseUrl",
2628
"build:website:blogOnly": "yarn workspace website build:blogOnly",
2729
"build:website:deployPreview:testWrap": "yarn workspace website test:swizzle:wrap:ts",

packages/docusaurus-faster/src/index.ts

+10
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ import browserslist from 'browserslist';
1111
import {minify as swcHtmlMinifier} from '@swc/html';
1212
import type {JsMinifyOptions, Options as SwcOptions} from '@swc/core';
1313

14+
// See https://rspack.dev/contribute/development/profiling
15+
// File can be opened with https://ui.perfetto.dev/
16+
if (process.env.DOCUSAURUS_RSPACK_TRACE) {
17+
Rspack.experiments.globalTrace.register(
18+
'trace',
19+
'chrome',
20+
'./rspack-tracing.json',
21+
);
22+
}
23+
1424
export const swcLoader = require.resolve('swc-loader');
1525

1626
export const getSwcLoaderOptions = ({

packages/docusaurus/src/commands/start/start.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8-
import logger from '@docusaurus/logger';
8+
import logger, {PerfLogger} from '@docusaurus/logger';
99
import openBrowser from '../utils/openBrowser/openBrowser';
1010
import {setupSiteFileWatchers} from './watcher';
1111
import {createWebpackDevServer} from './webpack';
@@ -21,7 +21,7 @@ export type StartCLIOptions = HostPortOptions &
2121
minify?: boolean;
2222
};
2323

24-
export async function start(
24+
async function doStart(
2525
siteDirParam: string = '.',
2626
cliOptions: Partial<StartCLIOptions> = {},
2727
): Promise<void> {
@@ -62,3 +62,10 @@ export async function start(
6262
await openBrowser(reloadableSite.getOpenUrl());
6363
}
6464
}
65+
66+
export async function start(
67+
siteDirParam: string = '.',
68+
cliOptions: Partial<StartCLIOptions> = {},
69+
): Promise<void> {
70+
return PerfLogger.async('CLI start', () => doStart(siteDirParam, cliOptions));
71+
}

packages/docusaurus/src/webpack/base.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ import fs from 'fs-extra';
99
import path from 'path';
1010
import {getCustomBabelConfigFilePath} from '@docusaurus/babel';
1111
import {
12+
createJsLoaderFactory,
1213
getCSSExtractPlugin,
1314
getMinimizers,
14-
createJsLoaderFactory,
1515
} from '@docusaurus/bundler';
1616

17-
import {md5Hash, getFileLoaderUtils} from '@docusaurus/utils';
18-
import {loadThemeAliases, loadDocusaurusAliases} from './aliases';
17+
import {getFileLoaderUtils, md5Hash} from '@docusaurus/utils';
18+
import {loadDocusaurusAliases, loadThemeAliases} from './aliases';
19+
import {BundlerCPUProfilerPlugin} from './plugins/BundlerCPUProfilerPlugin';
1920
import type {Configuration} from 'webpack';
2021
import type {
2122
ConfigureWebpackUtils,
@@ -339,6 +340,8 @@ export async function createBaseConfig({
339340
// for more reasoning
340341
ignoreOrder: true,
341342
}),
342-
],
343+
process.env.DOCUSAURUS_BUNDLER_CPU_PROFILE &&
344+
new BundlerCPUProfilerPlugin(),
345+
].filter(Boolean),
343346
};
344347
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import inspector from 'node:inspector';
9+
import fs from 'fs-extra';
10+
import type {Compiler} from 'webpack';
11+
12+
// Bundle CPU profiling plugin, contributed by the Rspack team
13+
// Can be opened in https://www.speedscope.app/
14+
// See also https://github.com/jerrykingxyz/docusaurus/pull/1
15+
// See also https://github.com/facebook/docusaurus/pull/10985
16+
export class BundlerCPUProfilerPlugin {
17+
output: string;
18+
19+
constructor(output?: string) {
20+
this.output = output ?? './bundler-cpu-profile.json';
21+
}
22+
23+
apply(compiler: Compiler): void {
24+
const session = new inspector.Session();
25+
session.connect();
26+
session.post('Profiler.enable');
27+
session.post('Profiler.start');
28+
29+
// In dev/watch mode, we restart the profiler before each compilation
30+
compiler.hooks.watchRun.tapPromise(
31+
BundlerCPUProfilerPlugin.name,
32+
async () => {
33+
session.post('Profiler.start');
34+
},
35+
);
36+
37+
compiler.hooks.done.tapPromise(BundlerCPUProfilerPlugin.name, async () => {
38+
session.post('Profiler.stop', (error, param) => {
39+
if (error) {
40+
console.error('Failed to generate JS CPU profile:', error);
41+
return;
42+
}
43+
fs.writeFile(this.output, JSON.stringify(param.profile)).catch(
44+
console.error,
45+
);
46+
});
47+
});
48+
}
49+
}

0 commit comments

Comments
 (0)