From 8aa84aa7f64bf58b6f2b71308c543d699a73d8d6 Mon Sep 17 00:00:00 2001 From: Timeless0911 Date: Thu, 29 Oct 2026 15:14:57 +0800 Subject: [PATCH] perf(core): optimize asset filename enumeration --- packages/core/src/asset/LibSvgrPatchPlugin.ts | 5 +++-- packages/core/src/css/LibCssExtractPlugin.ts | 5 +++-- packages/core/src/css/cssConfig.ts | 5 +++-- packages/core/src/plugins/ChunkAssetPlugin.ts | 5 +++-- packages/core/src/utils/compilation.ts | 7 +++++++ 5 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 packages/core/src/utils/compilation.ts diff --git a/packages/core/src/asset/LibSvgrPatchPlugin.ts b/packages/core/src/asset/LibSvgrPatchPlugin.ts index 18e8825e8c..eb666ca806 100644 --- a/packages/core/src/asset/LibSvgrPatchPlugin.ts +++ b/packages/core/src/asset/LibSvgrPatchPlugin.ts @@ -1,5 +1,6 @@ import { type Rspack, rspack } from '@rsbuild/core'; import { getUndoPath } from '../css/utils'; +import { getAssetNames } from '../utils/compilation'; const pluginName = 'LIB_SVGR_PATCH_PLUGIN'; @@ -9,9 +10,9 @@ export class LibSvgrPatchPlugin implements Rspack.RspackPluginInstance { readonly name: string = pluginName; apply(compiler: Rspack.Compiler): void { compiler.hooks.make.tap(this.name, (compilation) => { - compilation.hooks.processAssets.tap(this.name, (assets) => { + compilation.hooks.processAssets.tap(this.name, () => { const isEsm = Boolean(compilation.options.output.module); - const chunkAsset = Object.keys(assets).filter((name) => + const chunkAsset = getAssetNames(compilation).filter((name) => name.endsWith('js'), ); for (const name of chunkAsset) { diff --git a/packages/core/src/css/LibCssExtractPlugin.ts b/packages/core/src/css/LibCssExtractPlugin.ts index dc3f6a1487..5612d77df9 100644 --- a/packages/core/src/css/LibCssExtractPlugin.ts +++ b/packages/core/src/css/LibCssExtractPlugin.ts @@ -1,4 +1,5 @@ import { type Rspack, rspack } from '@rsbuild/core'; +import { getAssetNames } from '../utils/compilation'; import { ABSOLUTE_PUBLIC_PATH, AUTO_PUBLIC_PATH, @@ -26,8 +27,8 @@ class LibCssExtractPlugin implements Rspack.RspackPluginInstance { * replace publicPath placeholders of miniCssExtractLoader */ compiler.hooks.make.tap(pluginName, (compilation) => { - compilation.hooks.processAssets.tap(pluginName, (assets) => { - const chunkAsset = Object.keys(assets).filter((name) => + compilation.hooks.processAssets.tap(pluginName, () => { + const chunkAsset = getAssetNames(compilation).filter((name) => name.includes('.css'), ); for (const name of chunkAsset) { diff --git a/packages/core/src/css/cssConfig.ts b/packages/core/src/css/cssConfig.ts index 606ba4bf1e..881da30e8c 100644 --- a/packages/core/src/css/cssConfig.ts +++ b/packages/core/src/css/cssConfig.ts @@ -1,5 +1,6 @@ import type { EnvironmentConfig, RsbuildPlugin } from '@rsbuild/core'; import { createRequire } from 'node:module'; +import { getAssetNames } from '../utils/compilation'; import { LibCssExtractPlugin } from './LibCssExtractPlugin'; import { type CssLoaderOptionsAuto, @@ -97,8 +98,8 @@ const pluginLibCss = ( // 2. preserve CSS Modules asset api.processAssets( { stage: 'additional' }, // deleteAsset as soon as possible for small perf - ({ assets, compilation }) => { - for (const key of Object.keys(assets)) { + ({ compilation }) => { + for (const key of getAssetNames(compilation)) { if (RegExp(RSLIB_CSS_ENTRY_FLAG).exec(key)) { compilation.deleteAsset(key); } diff --git a/packages/core/src/plugins/ChunkAssetPlugin.ts b/packages/core/src/plugins/ChunkAssetPlugin.ts index 53b166dbca..256798de54 100644 --- a/packages/core/src/plugins/ChunkAssetPlugin.ts +++ b/packages/core/src/plugins/ChunkAssetPlugin.ts @@ -1,6 +1,7 @@ import { type EnvironmentConfig, type Rspack, rspack } from '@rsbuild/core'; import { JS_EXTENSIONS_PATTERN } from '../constant'; import type { DeepRequired, Format, Shims } from '../types'; +import { getAssetNames } from '../utils/compilation'; const PLUGIN_NAME = 'rsbuild:lib-chunk-asset'; const IMPORT_META_URL_SHIM = `const __rslib_import_meta_url__ = /*#__PURE__*/ (function () { @@ -68,8 +69,8 @@ class ChunkAssetPlugin { }); // The default stage runs before minification, which can remove unused shims. - compilation.hooks.processAssets.tap(PLUGIN_NAME, (assets) => { - const chunkAsset = Object.keys(assets).filter((name) => { + compilation.hooks.processAssets.tap(PLUGIN_NAME, () => { + const chunkAsset = getAssetNames(compilation).filter((name) => { return ( JS_EXTENSIONS_PATTERN.test(name) && jsChunkAssetNames.has(name) ); diff --git a/packages/core/src/utils/compilation.ts b/packages/core/src/utils/compilation.ts new file mode 100644 index 0000000000..6b855714ac --- /dev/null +++ b/packages/core/src/utils/compilation.ts @@ -0,0 +1,7 @@ +import type { Rspack } from '@rsbuild/core'; + +export function getAssetNames(compilation: Rspack.Compilation): string[] { + // The assets Proxy uses this method for ownKeys. Calling it directly avoids + // Proxy key validation and the per-asset descriptor lookups in Object.keys. + return compilation.__internal__getAssetFilenames(); +}