diff --git a/.changeset/thick-poets-count.md b/.changeset/thick-poets-count.md new file mode 100644 index 0000000000..da782a411f --- /dev/null +++ b/.changeset/thick-poets-count.md @@ -0,0 +1,7 @@ +--- +"@lynx-js/rspeedy": patch +--- + +Support `performance.printFileSize` + +Whether to print the file sizes after production build. diff --git a/packages/rspeedy/core/etc/rspeedy.api.md b/packages/rspeedy/core/etc/rspeedy.api.md index fbecbd08c2..b1dfbcc3df 100644 --- a/packages/rspeedy/core/etc/rspeedy.api.md +++ b/packages/rspeedy/core/etc/rspeedy.api.md @@ -6,6 +6,7 @@ import type { CreateRsbuildOptions } from '@rsbuild/core'; import { logger } from '@rsbuild/core'; +import type { PerformanceConfig } from '@rsbuild/core'; import type { RsbuildConfig } from '@rsbuild/core'; import type { RsbuildInstance } from '@rsbuild/core'; import { RsbuildPlugin } from '@rsbuild/core'; @@ -232,6 +233,7 @@ export interface Output { // @public export interface Performance { chunkSplit?: ChunkSplit | ChunkSplitBySize | ChunkSplitCustom | undefined; + printFileSize?: PerformanceConfig['printFileSize'] | undefined; removeConsole?: boolean | ConsoleType[] | undefined; } diff --git a/packages/rspeedy/core/src/config/performance/index.ts b/packages/rspeedy/core/src/config/performance/index.ts index 94370b2c36..012c22a6e9 100644 --- a/packages/rspeedy/core/src/config/performance/index.ts +++ b/packages/rspeedy/core/src/config/performance/index.ts @@ -1,6 +1,8 @@ // Copyright 2024 The Lynx Authors. All rights reserved. // Licensed under the Apache License Version 2.0 that can be found in the // LICENSE file in the root directory of this source tree. +import type { PerformanceConfig } from '@rsbuild/core' + import type { ChunkSplit, ChunkSplitBySize, @@ -67,4 +69,119 @@ export interface Performance { * ``` */ removeConsole?: boolean | ConsoleType[] | undefined + + /** + * Whether to print the file sizes after production build. + * + * {@link Performance.printFileSize} + * + * See {@link https://rsbuild.dev/config/performance/print-file-size | Rsbuild - performance.printFileSize} for details. + * + * @example + * + * If you don't want to print any information, you can disable it by setting printFileSize to false: + * + * ```ts + * import { defineConfig } from '@lynx-js/rspeedy' + * + * export default defineConfig({ + * performance: { + * printFileSize: false + * }, + * }) + * ``` + * + * @example + * + * Set total to false to disable total size output. + * + * ```ts + * import { defineConfig } from '@lynx-js/rspeedy' + * + * export default defineConfig({ + * performance: { + * printFileSize: { + * total: false, + * }, + * }, + * }) + * ``` + * + * @example + * + * Set detail to false to disable per-asset size output. + * + * If you don't need to view the size of each static asset, you can set detail to false. In this case, only the total size will be output: + * + * ```ts + * import { defineConfig } from '@lynx-js/rspeedy' + * + * export default defineConfig({ + * performance: { + * printFileSize: { + * detail: false, + * }, + * }, + * }) + * ``` + * + * @example + * + * If you don't need to view the gzipped size, you can set compressed to false. This can save some gzip computation time for large projects: + * + * ```ts + * import { defineConfig } from '@lynx-js/rspeedy' + * + * export default defineConfig({ + * performance: { + * printFileSize: { + * compressed: false, + * }, + * }, + * }) + * ``` + * + * @example + * + * To include only static assets that meet certain criteria, use a filter function with include. + * + * If returned false, the static asset will be excluded and not included in the total size or detailed size. + * + * only output static assets larger than 10kB: + * + * ```ts + * import { defineConfig } from '@lynx-js/rspeedy' + * + * export default defineConfig({ + * performance: { + * printFileSize: { + * include: (asset) => asset.size > 10 * 1000, + * } + * }, + * }) + * ``` + * + * @example + * + * To exclude static assets that meet certain criteria, use a filter function with exclude. If both include and exclude are set, exclude will take precedence. + * + * Rspeedy defaults to excluding source map, license files, and .d.ts type files, as these files do not affect page load performance. + * + * exclude .html files in addition to the default: + * + * ```ts + * import { defineConfig } from '@lynx-js/rspeedy' + * + * export default defineConfig({ + * performance: { + * printFileSize: { + * exclude: (asset) => + * /\.(?:map|LICENSE\.txt)$/.test(asset.name) || + * /\.html$/.test(asset.name), + * } + * }, + * }) + * ``` + */ + printFileSize?: PerformanceConfig['printFileSize'] | undefined } diff --git a/packages/rspeedy/core/src/config/rsbuild/index.ts b/packages/rspeedy/core/src/config/rsbuild/index.ts index ccec0d4c13..9636093f08 100644 --- a/packages/rspeedy/core/src/config/rsbuild/index.ts +++ b/packages/rspeedy/core/src/config/rsbuild/index.ts @@ -90,6 +90,8 @@ export function toRsbuildConfig( | ConsoleType[] | false | undefined, + + printFileSize: config.performance?.printFileSize ?? true, }, tools: { bundlerChain: config.tools?.bundlerChain, diff --git a/packages/rspeedy/core/test/config/performance.test-d.ts b/packages/rspeedy/core/test/config/performance.test-d.ts index 2d788a8974..d2638db4a0 100644 --- a/packages/rspeedy/core/test/config/performance.test-d.ts +++ b/packages/rspeedy/core/test/config/performance.test-d.ts @@ -213,4 +213,44 @@ describe('Config - Performance', () => { removeConsole: false, }) }) + + test('performance.printFileSize', () => { + assertType({ + printFileSize: undefined, + }) + assertType({ + printFileSize: {}, + }) + assertType({ + printFileSize: true, + }) + assertType({ + printFileSize: false, + }) + assertType({ + printFileSize: { + detail: false, + }, + }) + assertType({ + printFileSize: { + total: false, + }, + }) + assertType({ + printFileSize: { + compressed: false, + }, + }) + assertType({ + printFileSize: { + include: () => false, + }, + }) + assertType({ + printFileSize: { + exclude: () => true, + }, + }) + }) }) diff --git a/packages/rspeedy/core/test/config/rsbuild.test.ts b/packages/rspeedy/core/test/config/rsbuild.test.ts index f8e82978b3..8a2bd70495 100644 --- a/packages/rspeedy/core/test/config/rsbuild.test.ts +++ b/packages/rspeedy/core/test/config/rsbuild.test.ts @@ -450,6 +450,37 @@ describe('Config - toRsBuildConfig', () => { }) expect(rsbuildConfig.performance?.removeConsole).toBe(false) }) + + test('transform performance.printFileSize false', () => { + const rsbuildConfig = toRsbuildConfig({ + performance: { printFileSize: false }, + }) + expect(rsbuildConfig.performance?.printFileSize).toBe( + false, + ) + }) + + test('transform performance.printFileSize', () => { + const printFileSizeOptions = { + total: false, + detail: false, + compressed: true, + include: (_: { name: string, size: number }) => false, + exclude: (_: { name: string, size: number }) => false, + } + const rsbuildConfig = toRsbuildConfig({ + performance: { + printFileSize: printFileSizeOptions, + }, + }) + const printFileSize = rsbuildConfig.performance + ?.printFileSize as typeof printFileSizeOptions + expect(printFileSize.total).toBe(false) + expect(printFileSize.detail).toBe(false) + expect(printFileSize.compressed).toBe(true) + expect(printFileSize.include?.({ name: '', size: 1 })).toEqual(false) + expect(printFileSize.exclude?.({ name: '', size: 1 })).toEqual(false) + }) }) describe('Plugins', () => { diff --git a/packages/rspeedy/core/test/config/validate.test.ts b/packages/rspeedy/core/test/config/validate.test.ts index af27ce4295..3a6914acf9 100644 --- a/packages/rspeedy/core/test/config/validate.test.ts +++ b/packages/rspeedy/core/test/config/validate.test.ts @@ -1280,6 +1280,49 @@ describe('Config Validation', () => { { removeConsole: ['log', 'foo', 'bar'], }, + { + printFileSize: true, + }, + { + printFileSize: false, + }, + { + printFileSize: {}, + }, + { + printFileSize: { + total: false, + }, + }, + { + printFileSize: { + detail: false, + }, + }, + { + printFileSize: { + compressed: true, + }, + }, + { + printFileSize: { + include: () => false, + }, + }, + { + printFileSize: { + exclude: () => false, + }, + }, + { + printFileSize: { + total: false, + detail: false, + compressed: true, + include: () => false, + exclude: () => false, + }, + }, ] cases.forEach(performance => { @@ -1442,6 +1485,57 @@ describe('Config Validation', () => { - Got: string ] `) + + expect(() => + validate({ + performance: { + printFileSize: { + detail: 0, + }, + }, + }) + ).toThrowErrorMatchingInlineSnapshot(` + [Error: Invalid configuration. + + Invalid config on \`$input.performance.printFileSize.detail\`. + - Expect to be (boolean | undefined) + - Got: number + ] + `) + + expect(() => + validate({ + performance: { + printFileSize: { + total: 0, + }, + }, + }) + ).toThrowErrorMatchingInlineSnapshot(` + [Error: Invalid configuration. + + Invalid config on \`$input.performance.printFileSize.total\`. + - Expect to be (boolean | undefined) + - Got: number + ] + `) + + expect(() => + validate({ + performance: { + printFileSize: { + compressed: 0, + }, + }, + }) + ).toThrowErrorMatchingInlineSnapshot(` + [Error: Invalid configuration. + + Invalid config on \`$input.performance.printFileSize.compressed\`. + - Expect to be (boolean | undefined) + - Got: number + ] + `) }) })