From 071d09457691a649b233978395eadcbb32ea1726 Mon Sep 17 00:00:00 2001 From: neverland Date: Wed, 23 Oct 2024 19:16:32 +0800 Subject: [PATCH 1/4] feat: add new `output.assetsInclude` config --- packages/core/src/plugins/asset.ts | 19 +++++++++++++++++++ packages/core/src/types/config.ts | 5 +++++ 2 files changed, 24 insertions(+) diff --git a/packages/core/src/plugins/asset.ts b/packages/core/src/plugins/asset.ts index 958588600..b317c5cf6 100644 --- a/packages/core/src/plugins/asset.ts +++ b/packages/core/src/plugins/asset.ts @@ -2,6 +2,7 @@ import path from 'node:path'; import type { GeneratorOptionsByModuleType } from '@rspack/core'; import { AUDIO_EXTENSIONS, + DEFAULT_DATA_URL_SIZE, FONT_EXTENSIONS, IMAGE_EXTENSIONS, VIDEO_EXTENSIONS, @@ -126,6 +127,24 @@ export const pluginAsset = (): RsbuildPlugin => ({ if (!emitAssets) { chain.module.generator.merge({ 'asset/resource': { emit: false } }); } + + // additional assets + if (config.output.assetsInclude) { + const { assetsInclude, dataUriLimit } = config.output; + const rule = chain.module.rule('additional-assets').test(assetsInclude); + const maxSize = + typeof dataUriLimit === 'number' + ? dataUriLimit + : DEFAULT_DATA_URL_SIZE; + + chainStaticAssetRule({ + emit: emitAssets, + rule, + maxSize, + filename: assetsFilename, + assetType: 'additional', + }); + } }); }, }); diff --git a/packages/core/src/types/config.ts b/packages/core/src/types/config.ts index aab0b6b65..709e85cc3 100644 --- a/packages/core/src/types/config.ts +++ b/packages/core/src/types/config.ts @@ -863,6 +863,11 @@ export interface OutputConfig { * @default `server.base` */ assetPrefix?: string; + /** + * Include additional files that should be treated as static assets. + * @default undefined + */ + assetsInclude?: Rspack.RuleSetCondition; /** * Set the size threshold to inline static assets such as images and fonts. * By default, static assets will be Base64 encoded and inline into the page if the size is less than 4KiB. From 6a2387a569bf8f6ccfed1fd9029b5f900e627a84 Mon Sep 17 00:00:00 2001 From: neverland Date: Wed, 23 Oct 2024 22:00:52 +0800 Subject: [PATCH 2/4] fix --- packages/core/src/plugins/asset.ts | 5 +++-- packages/core/src/types/config.ts | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/core/src/plugins/asset.ts b/packages/core/src/plugins/asset.ts index b317c5cf6..38efb9890 100644 --- a/packages/core/src/plugins/asset.ts +++ b/packages/core/src/plugins/asset.ts @@ -129,8 +129,9 @@ export const pluginAsset = (): RsbuildPlugin => ({ } // additional assets - if (config.output.assetsInclude) { - const { assetsInclude, dataUriLimit } = config.output; + const { assetsInclude } = config.source; + if (assetsInclude) { + const { dataUriLimit } = config.output; const rule = chain.module.rule('additional-assets').test(assetsInclude); const maxSize = typeof dataUriLimit === 'number' diff --git a/packages/core/src/types/config.ts b/packages/core/src/types/config.ts index 709e85cc3..942fd1561 100644 --- a/packages/core/src/types/config.ts +++ b/packages/core/src/types/config.ts @@ -183,6 +183,11 @@ export interface SourceConfig { * and the `alias` option in the bundler. */ aliasStrategy?: AliasStrategy; + /** + * Include additional files that should be treated as static assets. + * @default undefined + */ + assetsInclude?: Rspack.RuleSetCondition; /** * Specify directories or modules that need additional compilation. * In order to maintain faster compilation speed, Rsbuild will not compile files under node_modules through @@ -863,11 +868,6 @@ export interface OutputConfig { * @default `server.base` */ assetPrefix?: string; - /** - * Include additional files that should be treated as static assets. - * @default undefined - */ - assetsInclude?: Rspack.RuleSetCondition; /** * Set the size threshold to inline static assets such as images and fonts. * By default, static assets will be Base64 encoded and inline into the page if the size is less than 4KiB. From 8dfacb9add1bfb2570e2316cb9fd44da4b5b1f41 Mon Sep 17 00:00:00 2001 From: neverland Date: Wed, 23 Oct 2024 22:31:05 +0800 Subject: [PATCH 3/4] test --- .../assets/addtional-assets/index.test.ts | 46 +++++++++++++++++++ .../assets/addtional-assets/rsbuild.config.ts | 21 +++++++++ .../assets/addtional-assets/src/index.js | 5 ++ 3 files changed, 72 insertions(+) create mode 100644 e2e/cases/assets/addtional-assets/index.test.ts create mode 100644 e2e/cases/assets/addtional-assets/rsbuild.config.ts create mode 100644 e2e/cases/assets/addtional-assets/src/index.js diff --git a/e2e/cases/assets/addtional-assets/index.test.ts b/e2e/cases/assets/addtional-assets/index.test.ts new file mode 100644 index 000000000..d6d132258 --- /dev/null +++ b/e2e/cases/assets/addtional-assets/index.test.ts @@ -0,0 +1,46 @@ +import { build } from '@e2e/helper'; +import { expect, test } from '@playwright/test'; + +function isIncludeFile(filenames: string[], includeFilename: string) { + return filenames.some((filename) => filename.includes(includeFilename)); +} + +test('should allow to configure additional assets', async () => { + const rsbuild = await build({ + cwd: __dirname, + }); + + const files = await rsbuild.unwrapOutputJSON(); + const filenames = Object.keys(files); + + const indexJs = await rsbuild.getIndexFile(); + expect(indexJs.content).toContain('data:application/json5;base64,'); + + expect( + isIncludeFile(filenames, 'dist/static/assets/test-temp-large.json5'), + ).toBeTruthy(); + expect( + isIncludeFile(filenames, 'dist/static/assets/test-temp-small.json5'), + ).toBeFalsy(); +}); + +test('should allow to disable emit for additional assets', async () => { + const rsbuild = await build({ + cwd: __dirname, + rsbuildConfig: { + output: { + emitAssets: false, + }, + }, + }); + + const files = await rsbuild.unwrapOutputJSON(); + const filenames = Object.keys(files); + + expect( + isIncludeFile(filenames, 'dist/static/assets/test-temp-large.json5'), + ).toBeFalsy(); + expect( + isIncludeFile(filenames, 'dist/static/assets/test-temp-small.json5'), + ).toBeFalsy(); +}); diff --git a/e2e/cases/assets/addtional-assets/rsbuild.config.ts b/e2e/cases/assets/addtional-assets/rsbuild.config.ts new file mode 100644 index 000000000..8b37173c6 --- /dev/null +++ b/e2e/cases/assets/addtional-assets/rsbuild.config.ts @@ -0,0 +1,21 @@ +import { writeFileSync } from 'node:fs'; +import { join } from 'node:path'; +import { defineConfig } from '@rsbuild/core'; + +writeFileSync( + join(__dirname, 'src/test-temp-small.json5'), + JSON.stringify({ a: 1 }), +); +writeFileSync( + join(__dirname, 'src/test-temp-large.json5'), + JSON.stringify({ a: '1'.repeat(10000) }), +); + +export default defineConfig({ + source: { + assetsInclude: /\.json5$/, + }, + output: { + filenameHash: false, + }, +}); diff --git a/e2e/cases/assets/addtional-assets/src/index.js b/e2e/cases/assets/addtional-assets/src/index.js new file mode 100644 index 000000000..789f70777 --- /dev/null +++ b/e2e/cases/assets/addtional-assets/src/index.js @@ -0,0 +1,5 @@ +import large from './test-temp-large.json5'; +import small from './test-temp-small.json5'; + +console.log(large); +console.log(small); From 20a5e2d1e0b7a742edbcfba6bf30e2001d65ed1c Mon Sep 17 00:00:00 2001 From: neverland Date: Thu, 24 Oct 2024 11:12:26 +0800 Subject: [PATCH 4/4] docs: add doc --- .../assets/addtional-assets/index.test.ts | 35 ++++++++++++++- .../assets/addtional-assets/rsbuild.config.ts | 13 +++--- .../assets/addtional-assets/src/index.js | 4 +- .../docs/en/config/source/assets-include.mdx | 44 +++++++++++++++++++ website/docs/en/config/source/exclude.mdx | 2 +- website/docs/en/config/source/include.mdx | 2 +- .../docs/zh/config/source/assets-include.mdx | 44 +++++++++++++++++++ 7 files changed, 131 insertions(+), 13 deletions(-) create mode 100644 website/docs/en/config/source/assets-include.mdx create mode 100644 website/docs/zh/config/source/assets-include.mdx diff --git a/e2e/cases/assets/addtional-assets/index.test.ts b/e2e/cases/assets/addtional-assets/index.test.ts index d6d132258..c76f1bd7c 100644 --- a/e2e/cases/assets/addtional-assets/index.test.ts +++ b/e2e/cases/assets/addtional-assets/index.test.ts @@ -1,3 +1,4 @@ +import path from 'node:path'; import { build } from '@e2e/helper'; import { expect, test } from '@playwright/test'; @@ -5,9 +6,38 @@ function isIncludeFile(filenames: string[], includeFilename: string) { return filenames.some((filename) => filename.includes(includeFilename)); } -test('should allow to configure additional assets', async () => { +test('should allow to configure additional assets and match by RegExp', async () => { const rsbuild = await build({ cwd: __dirname, + rsbuildConfig: { + source: { + assetsInclude: [/\.json5$/], + }, + }, + }); + + const files = await rsbuild.unwrapOutputJSON(); + const filenames = Object.keys(files); + + const indexJs = await rsbuild.getIndexFile(); + expect(indexJs.content).toContain('data:application/json5;base64,'); + + expect( + isIncludeFile(filenames, 'dist/static/assets/test-temp-large.json5'), + ).toBeTruthy(); + expect( + isIncludeFile(filenames, 'dist/static/assets/test-temp-small.json5'), + ).toBeFalsy(); +}); + +test('should allow to configure additional assets and match by path', async () => { + const rsbuild = await build({ + cwd: __dirname, + rsbuildConfig: { + source: { + assetsInclude: path.resolve(__dirname, 'src/assets'), + }, + }, }); const files = await rsbuild.unwrapOutputJSON(); @@ -28,6 +58,9 @@ test('should allow to disable emit for additional assets', async () => { const rsbuild = await build({ cwd: __dirname, rsbuildConfig: { + source: { + assetsInclude: [/\.json5$/], + }, output: { emitAssets: false, }, diff --git a/e2e/cases/assets/addtional-assets/rsbuild.config.ts b/e2e/cases/assets/addtional-assets/rsbuild.config.ts index 8b37173c6..3ca8395f8 100644 --- a/e2e/cases/assets/addtional-assets/rsbuild.config.ts +++ b/e2e/cases/assets/addtional-assets/rsbuild.config.ts @@ -1,20 +1,17 @@ -import { writeFileSync } from 'node:fs'; import { join } from 'node:path'; import { defineConfig } from '@rsbuild/core'; +import { outputFileSync } from 'fs-extra'; -writeFileSync( - join(__dirname, 'src/test-temp-small.json5'), +outputFileSync( + join(__dirname, 'src/assets/test-temp-small.json5'), JSON.stringify({ a: 1 }), ); -writeFileSync( - join(__dirname, 'src/test-temp-large.json5'), +outputFileSync( + join(__dirname, 'src/assets/test-temp-large.json5'), JSON.stringify({ a: '1'.repeat(10000) }), ); export default defineConfig({ - source: { - assetsInclude: /\.json5$/, - }, output: { filenameHash: false, }, diff --git a/e2e/cases/assets/addtional-assets/src/index.js b/e2e/cases/assets/addtional-assets/src/index.js index 789f70777..97d0c583b 100644 --- a/e2e/cases/assets/addtional-assets/src/index.js +++ b/e2e/cases/assets/addtional-assets/src/index.js @@ -1,5 +1,5 @@ -import large from './test-temp-large.json5'; -import small from './test-temp-small.json5'; +import large from './assets/test-temp-large.json5'; +import small from './assets/test-temp-small.json5'; console.log(large); console.log(small); diff --git a/website/docs/en/config/source/assets-include.mdx b/website/docs/en/config/source/assets-include.mdx new file mode 100644 index 000000000..1c91a6314 --- /dev/null +++ b/website/docs/en/config/source/assets-include.mdx @@ -0,0 +1,44 @@ +# source.assetsInclude + +- **Type:** [Rspack.RuleSetCondition](https://rspack.dev/config/module#condition) +- **Default:** `undefined` + +Include additional files that should be treated as static assets. + +By default, Rsbuild treats common image, font, audio, and video files as static assets. Through the `source.assetsInclude` config, you can specify additional file types that should be treated as static assets. These added static assets are processed using the same rules as the built-in supported static assets, see [Static Assets](/guide/basic/static-assets). + +The value of `source.assetsInclude` is the same as the `test` option in Rspack loader. It can be a regular expression, string, array, logical condition, etc. For more details, see [Rspack RuleSetCondition](https://rspack.dev/config/module#condition). + +## Example + +- Treating `.json5` files as static assets: + +```ts +export default defineConfig({ + source: { + assetsInclude: /\.json5$/, + }, +}); +``` + +- Treating multiple file types as static assets: + +```ts +export default defineConfig({ + source: { + assetsInclude: [/\.json5$/, /\.pdf$/], + }, +}); +``` + +- Treating specific files as static assets: + +```ts +import path from 'node:path'; + +export default defineConfig({ + source: { + assetsInclude: path.resolve(__dirname, 'src/assets/foo.json5'), + }, +}); +``` diff --git a/website/docs/en/config/source/exclude.mdx b/website/docs/en/config/source/exclude.mdx index c74e3032b..c5d23ab55 100644 --- a/website/docs/en/config/source/exclude.mdx +++ b/website/docs/en/config/source/exclude.mdx @@ -1,6 +1,6 @@ # source.exclude -- **Type:** [RuleSetCondition[]](https://rspack.dev/config/module#condition) +- **Type:** [Rspack.RuleSetCondition](https://rspack.dev/config/module#condition) - **Default:** `[]` Specifies JavaScript/TypeScript files that do not need to be compiled. The usage is consistent with [Rule.exclude](https://rspack.dev/config/module#ruleexclude) in Rspack, which supports passing in strings or regular expressions to match the module path. diff --git a/website/docs/en/config/source/include.mdx b/website/docs/en/config/source/include.mdx index ca11d10a9..86d86188f 100644 --- a/website/docs/en/config/source/include.mdx +++ b/website/docs/en/config/source/include.mdx @@ -1,6 +1,6 @@ # source.include -- **Type:** [RuleSetCondition[]](https://rspack.dev/config/module#condition) +- **Type:** [Rspack.RuleSetCondition](https://rspack.dev/config/module#condition) - **Default:** ```ts diff --git a/website/docs/zh/config/source/assets-include.mdx b/website/docs/zh/config/source/assets-include.mdx new file mode 100644 index 000000000..9b3e01957 --- /dev/null +++ b/website/docs/zh/config/source/assets-include.mdx @@ -0,0 +1,44 @@ +# source.assetsInclude + +- **类型:** [Rspack.RuleSetCondition](https://rspack.dev/config/module#condition) +- **默认值:** `undefined` + +指定需要被视为静态资源的额外文件类型。 + +Rsbuild 默认会将常见的图片、字体、音频、视频等文件视为静态资源。通过配置 `source.assetsInclude`,你可以添加更多的文件类型,这些新增的静态资源将按照与内置静态资源相同的规则进行处理,详见 [引用静态资源](/guide/basic/static-assets)。 + +`source.assetsInclude` 的值与 Rspack loader 的 `test` 选项相同,可以是正则表达式、字符串、数组、逻辑条件等,详见 [Rspack RuleSetCondition](https://rspack.dev/config/module#condition)。 + +## 示例 + +- 将 `.json5` 文件视为静态资源: + +```ts +export default defineConfig({ + source: { + assetsInclude: /\.json5$/, + }, +}); +``` + +- 将多种文件类型视为静态资源: + +```ts +export default defineConfig({ + source: { + assetsInclude: [/\.json5$/, /\.pdf$/], + }, +}); +``` + +- 将指定文件视为静态资源: + +```ts +import path from 'node:path'; + +export default defineConfig({ + source: { + assetsInclude: path.resolve(__dirname, 'src/assets/foo.json5'), + }, +}); +```