Skip to content

Commit 2fcc000

Browse files
authored
feat(angular-rspack): add statsJson plugin (#79)
1 parent 86a0824 commit 2fcc000

File tree

8 files changed

+67
-2
lines changed

8 files changed

+67
-2
lines changed

e2e/fixtures/rspack-csr-scss/rspack.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ module.exports = () => {
1414
tsConfig: './tsconfig.app.json',
1515
polyfills: ['zone.js'],
1616
assets: [{ glob: '**/*', input: 'public' }],
17+
statsJson: true,
1718
styles: ['./src/styles.scss'],
1819
stylePreprocessorOptions: {
1920
includePaths: ['../shared/styles/src'],

packages/angular-rspack/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"dependencies": {
5252
"@ampproject/remapping": "2.3.0",
5353
"@babel/core": "7.26.10",
54+
"@discoveryjs/json-ext": "0.6.3",
5455
"@nx/angular-rspack-compiler": "workspace:*",
5556
"@nx/devkit": "21.0.0",
5657
"autoprefixer": "10.4.21",

packages/angular-rspack/src/lib/config/config-utils/common-config.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { type Configuration, javascript } from '@rspack/core';
2+
import { resolve } from 'node:path';
23
import {
34
JS_ALL_EXT_REGEX,
45
TS_ALL_EXT_REGEX,
@@ -11,6 +12,7 @@ import {
1112
import { getStylesConfig } from './style-config-utils';
1213
import { getCrossOriginLoading } from './helpers';
1314
import { configureSourceMap } from './sourcemap-utils';
15+
import { StatsJsonPlugin } from '../../plugins/stats-json-plugin';
1416

1517
export async function getCommonConfig(
1618
normalizedOptions: NormalizedAngularRspackPluginOptions,
@@ -29,6 +31,7 @@ export async function getCommonConfig(
2931

3032
const defaultConfig: Configuration = {
3133
context: normalizedOptions.root,
34+
profile: normalizedOptions.statsJson,
3235
mode: isProduction ? 'production' : 'development',
3336
devtool: normalizedOptions.sourceMap.scripts ? 'source-map' : undefined,
3437
output: {
@@ -111,6 +114,17 @@ export async function getCommonConfig(
111114
},
112115
plugins: [
113116
...sourceMapOptions.sourceMapPlugins,
117+
...(normalizedOptions.statsJson
118+
? [
119+
new StatsJsonPlugin(
120+
resolve(
121+
normalizedOptions.root,
122+
normalizedOptions.outputPath.base,
123+
'stats.json'
124+
)
125+
),
126+
]
127+
: []),
114128
...(i18n.shouldInline
115129
? [
116130
{

packages/angular-rspack/src/lib/models/angular-rspack-plugin-options.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ export interface AngularRspackPluginOptions extends PluginUnsupportedOptions {
224224
entry: string;
225225
experimentalPlatform?: 'node' | 'neutral';
226226
};
227+
/**
228+
* Generates a 'stats.json' file which can be analyzed using tools such as 'webpack-bundle-analyzer'.
229+
*/
230+
statsJson?: boolean;
227231
stylePreprocessorOptions?: StylePreprocessorOptions;
228232
styles?: ScriptOrStyleEntry[];
229233
/**

packages/angular-rspack/src/lib/models/normalize-options.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ export async function normalizeOptions(
287287
skipTypeChecking: options.skipTypeChecking ?? false,
288288
sourceMap: normalizeSourceMap(options.sourceMap),
289289
ssr: normalizedSsr,
290+
statsJson: options.statsJson ?? false,
290291
stylePreprocessorOptions: options.stylePreprocessorOptions,
291292
subresourceIntegrity: options.subresourceIntegrity ?? false,
292293
supportedBrowsers: getSupportedBrowsers(root, { warn: console.warn }),

packages/angular-rspack/src/lib/models/unsupported-options.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ export interface PluginUnsupportedOptions {
4040
progress?: boolean;
4141
watch?: boolean;
4242
poll?: number;
43-
statsJson?: boolean;
4443
budgets?: BudgetEntry[];
4544
allowedCommonJsDependencies?: string[];
4645
appShell?: boolean;
@@ -54,7 +53,6 @@ export const TOP_LEVEL_OPTIONS_PENDING_SUPPORT = [
5453
'progress',
5554
'watch',
5655
'poll',
57-
'statsJson',
5856
'budgets',
5957
'allowedCommonJsDependencies',
6058
'appShell',
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.dev/license
7+
*/
8+
9+
import { createWriteStream } from 'node:fs';
10+
import { mkdir } from 'node:fs/promises';
11+
import { dirname } from 'node:path';
12+
import { pipeline } from 'node:stream/promises';
13+
import type { RspackPluginInstance, Compiler } from '@rspack/core';
14+
import { assertIsError } from '../utils/misc-helpers';
15+
import { addError } from '../utils/rspack-diagnostics';
16+
17+
export class StatsJsonPlugin implements RspackPluginInstance {
18+
constructor(private readonly statsOutputPath: string) {}
19+
20+
apply(compiler: Compiler) {
21+
compiler.hooks.done.tapPromise(
22+
'AngularRspackStatsJsonPlugin',
23+
async (stats) => {
24+
const { stringifyChunked } = await import('@discoveryjs/json-ext');
25+
const data = stats.toJson('verbose');
26+
27+
try {
28+
await mkdir(dirname(this.statsOutputPath), { recursive: true });
29+
await pipeline(
30+
stringifyChunked(data),
31+
createWriteStream(this.statsOutputPath)
32+
);
33+
} catch (error) {
34+
assertIsError(error);
35+
addError(
36+
stats.compilation,
37+
`Unable to write stats file: ${error.message || 'unknown error'}`
38+
);
39+
}
40+
}
41+
);
42+
}
43+
}

pnpm-lock.yaml

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

0 commit comments

Comments
 (0)