From fd36ce1bebdf0c381cb6f724638f19a96d4ef136 Mon Sep 17 00:00:00 2001 From: zhangxiang Date: Fri, 31 Oct 2025 17:10:32 +0800 Subject: [PATCH 1/3] feat: align rsbuild config --- .changeset/five-ghosts-care.md | 7 +++ .../builder/src/shared/parseCommonConfig.ts | 5 +- packages/cli/builder/src/shared/utils.ts | 9 ++- packages/cli/builder/src/types.ts | 2 +- .../en/components/upgrade-browserslist.mdx | 0 .../docs/en/configure/app/html/app-icon.mdx | 24 +------ .../configure/app/output/inline-scripts.mdx | 2 +- .../app/output/override-browserslist.mdx | 10 +-- .../advanced-features/compatibility.mdx | 62 ++++++++++++++++--- .../page-performance/optimize-bundle.mdx | 10 +-- .../zh/components/upgrade-browserslist.mdx | 0 .../docs/zh/configure/app/html/app-icon.mdx | 24 +------ .../configure/app/output/inline-scripts.mdx | 2 +- .../app/output/override-browserslist.mdx | 6 +- .../advanced-features/compatibility.mdx | 44 +++++++++++++ .../page-performance/optimize-bundle.mdx | 10 +-- .../app-tools/src/config/initialize/inits.ts | 8 ++- packages/toolkit/utils/src/cli/get/data.ts | 7 ++- 18 files changed, 148 insertions(+), 84 deletions(-) create mode 100644 .changeset/five-ghosts-care.md create mode 100644 packages/document/main-doc/docs/en/components/upgrade-browserslist.mdx create mode 100644 packages/document/main-doc/docs/zh/components/upgrade-browserslist.mdx diff --git a/.changeset/five-ghosts-care.md b/.changeset/five-ghosts-care.md new file mode 100644 index 000000000000..a0dc0d074d1d --- /dev/null +++ b/.changeset/five-ghosts-care.md @@ -0,0 +1,7 @@ +--- +'@modern-js/utils': patch +'@modern-js/builder': patch +--- + +feat: align rsbuild config +feat: 对齐 rsbuild 配置 diff --git a/packages/cli/builder/src/shared/parseCommonConfig.ts b/packages/cli/builder/src/shared/parseCommonConfig.ts index eb41fa63d945..f70cd37a71e1 100644 --- a/packages/cli/builder/src/shared/parseCommonConfig.ts +++ b/packages/cli/builder/src/shared/parseCommonConfig.ts @@ -166,10 +166,7 @@ export async function parseCommonConfig( html.title ??= ''; - html.appIcon = - typeof appIcon === 'string' - ? { icons: [{ src: appIcon, size: 180 }] } - : appIcon; + html.appIcon = appIcon; extraConfig.tools ??= {}; diff --git a/packages/cli/builder/src/shared/utils.ts b/packages/cli/builder/src/shared/utils.ts index f3089f790ad1..754e7b497e26 100644 --- a/packages/cli/builder/src/shared/utils.ts +++ b/packages/cli/builder/src/shared/utils.ts @@ -49,11 +49,16 @@ export const isHtmlDisabled = ( ); }; -const DEFAULT_WEB_BROWSERSLIST = ['> 0.01%', 'not dead', 'not op_mini all']; +const DEFAULT_WEB_BROWSERSLIST = [ + 'chrome >= 87', + 'edge >= 88', + 'firefox >= 78', + 'safari >= 14', +]; const DEFAULT_BROWSERSLIST: Record = { web: DEFAULT_WEB_BROWSERSLIST, - node: ['node >= 14'], + node: ['node >= 16'], 'web-worker': DEFAULT_WEB_BROWSERSLIST, }; diff --git a/packages/cli/builder/src/types.ts b/packages/cli/builder/src/types.ts index 8f32dd55ab28..27699038c1e4 100644 --- a/packages/cli/builder/src/types.ts +++ b/packages/cli/builder/src/types.ts @@ -200,7 +200,7 @@ export type BuilderExtraConfig = { disableSvgr?: boolean; }; html?: { - appIcon?: string | HtmlConfig['appIcon']; + appIcon?: HtmlConfig['appIcon']; // TODO: need support rsbuild favicon type in server/utils favicon?: string; }; diff --git a/packages/document/main-doc/docs/en/components/upgrade-browserslist.mdx b/packages/document/main-doc/docs/en/components/upgrade-browserslist.mdx new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/document/main-doc/docs/en/configure/app/html/app-icon.mdx b/packages/document/main-doc/docs/en/configure/app/html/app-icon.mdx index 8cc73f5f89e5..f7ca0b9c0773 100644 --- a/packages/document/main-doc/docs/en/configure/app/html/app-icon.mdx +++ b/packages/document/main-doc/docs/en/configure/app/html/app-icon.mdx @@ -13,7 +13,7 @@ type AppIconItem = { target?: 'apple-touch-icon' | 'web-app-manifest'; }; -type AppIcon = string | { +type AppIcon = { name?: string; icons: AppIconItem[]; filename?: string; @@ -27,28 +27,6 @@ Set the web application icons to display when added to the home screen of a mobi - Generate the web app manifest file and its `icons` field. - Generate the `apple-touch-icon` and `manifest` tags in the HTML file. -### AppIcon string - -The `appIcon` configuration of type `string` is a syntactic sugar for the `object` type. - -```js -export default { - html: { - appIcon: './src/assets/icon.png', - }, -}; -``` - -The above configuration is equivalent to the following configuration: - -```js -export default { - html: { - appIcon: { icons: [{ src: './src/assets/icon.png', size: 180 }] } - }, -}; -``` - import RsbuildConfig from '@site-docs-en/components/rsbuild-config-tooltip'; diff --git a/packages/document/main-doc/docs/en/configure/app/output/inline-scripts.mdx b/packages/document/main-doc/docs/en/configure/app/output/inline-scripts.mdx index 186a485cb2ef..d69772fcf7a0 100644 --- a/packages/document/main-doc/docs/en/configure/app/output/inline-scripts.mdx +++ b/packages/document/main-doc/docs/en/configure/app/output/inline-scripts.mdx @@ -20,7 +20,7 @@ type InlineScripts = }; ``` -- **Default:** `false` +- **Default:** `/builder-runtime([.].+)?\.js$/` Whether to inline output scripts files (.js files) into HTML with `'); -}); diff --git a/tests/e2e/builder/cases/html/cross-origin/src/index.js b/tests/e2e/builder/cases/html/cross-origin/src/index.js deleted file mode 100644 index 4748527e94fa..000000000000 --- a/tests/e2e/builder/cases/html/cross-origin/src/index.js +++ /dev/null @@ -1 +0,0 @@ -console.log('1'); diff --git a/tests/e2e/builder/cases/html/favicon/index.test.ts b/tests/e2e/builder/cases/html/favicon/index.test.ts deleted file mode 100644 index 1091d3388969..000000000000 --- a/tests/e2e/builder/cases/html/favicon/index.test.ts +++ /dev/null @@ -1,66 +0,0 @@ -import path from 'path'; -import { expect, test } from '@playwright/test'; -import { build } from '@scripts/shared'; - -test('should emit local favicon to dist path', async () => { - const builder = await build({ - cwd: __dirname, - entry: { index: path.resolve(__dirname, './src/index.js') }, - builderConfig: { - html: { - favicon: './src/icon.png', - }, - }, - }); - const files = await builder.unwrapOutputJSON(); - - expect( - Object.keys(files).some(file => file.endsWith('/icon.png')), - ).toBeTruthy(); - - const html = - files[Object.keys(files).find(file => file.endsWith('index.html'))!]; - - expect(html).toContain(''); -}); - -test('should apply asset prefix to favicon URL', async () => { - const builder = await build({ - cwd: __dirname, - entry: { index: path.resolve(__dirname, './src/index.js') }, - builderConfig: { - html: { - favicon: './src/icon.png', - }, - output: { - assetPrefix: 'https://www.example.com', - }, - }, - }); - const files = await builder.unwrapOutputJSON(); - - const html = - files[Object.keys(files).find(file => file.endsWith('index.html'))!]; - - expect(html).toContain( - '', - ); -}); - -test('should allow favicon to be a CDN URL', async () => { - const builder = await build({ - cwd: __dirname, - entry: { index: path.resolve(__dirname, './src/index.js') }, - builderConfig: { - html: { - favicon: 'https://foo.com/icon.png', - }, - }, - }); - const files = await builder.unwrapOutputJSON(); - - const html = - files[Object.keys(files).find(file => file.endsWith('index.html'))!]; - - expect(html).toContain(''); -}); diff --git a/tests/e2e/builder/cases/html/favicon/src/icon.png b/tests/e2e/builder/cases/html/favicon/src/icon.png deleted file mode 100644 index be09a3a0ff209d8ad0b7b1fd95841e470aade148..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1918 zcmV-^2Z8vBP) z(?%G_pOu{#(#+}lkJy4upIuoXi3n7$5(z1`_O=MXwyV5F=f_^g@tQRZz@BjbVXIBD%f`WpA zf`WpAOfmoWsy@H5sz;qyh60=V#%gWUD9@ObED)kyeqrwDzyI^B%?{0mz3+_{5M5>t zk6Z=|7QnP-EFd*P0M=eUhsQ6Tbq&M#%0BVhlNz*6b^WeE;092L}G61T(kG(Vv zc=&t+Hnz9BKw%E1&$r==wWSl4YICYmooz3Zw)c96-hmj+A!}rjSWu_Ls$0}?856JX zytS8`=sGZ{)d9_#gO4tDP`qJMYM!iA!35~|UH?!Dh%U3Be3k;O6NA>dScDD+Zr61? zuW+*iWLLaJptN~<;vL+-!rbQ@;X@&yJpk+sEto*gf<_n6WxxtsRDE)}4maCOyeqbN zSD!2}@miCk6L6$FjPidIbdB5!=yjPzdIgoPAM*CDrTpKUg;R!@u5+BHwkeck|_b*%`9lJNYG^#g{1hn4#$=2 zaOOhOe(e&^9bJTt*muINec%EHHM5Xhw;cY;8j@=-0 zJmMjK(M1UMhyp}@_CA*Zy6j-tVWa9_Tbur_v*=Bjo^SZR(ODd5xp!f7^|9l=r$1OG zLcR!e;Q6PImMAeB2k9~||8Bp6-!?bw{?3;YUH0Ao8JpjF#0!dUkHEzPFTMhvTVG{E zyVcy!S{4Sn?$2Id7ecqM*16GOK&hbU+7P%6f@pp_zn`3Kvu{kO2BZzT?x&6QDDjXQ ztlsvwRIgFy_>H=5MA{dQ7Ifgd$?0ncDI&V=kIgRJ|L+R6JymnHv-}z0?|dJ;)@6ih^Q7(VubZaP`s#7cNdBFg(D>(qC&*Pu0sUH ziyC#^$h0q<*qw6RnwY58aRkLfaD`dKeb~PIyi8_65@`o=WSywQb%=y`!qIh*b{`U3 zKtxo;#I=qiA)ZWh5e>p`9tELfvKtiVM17qX3Gooo==P9qUpR>z$nkTcGS?xJ;z>pq zi4|W&iGTC~cc-__xlqf%{BZKwjLCniCX z6;}V|ASMU*WP)?A0)INb$FDwV$$Y)|G{O60Z-Xo}LH$FN)xZ?!%A9Koh+C z7DSex&Jq@IygUL^l?jjq@BKcISi15fyAC7)(e{AR)yL%qn!R6<%za3fBP>MR=ps>% zu8ELc0co@Y<3^Wb&}0J$l3fAI;Q}U!ZjZ=E*F?x|geRHv;zk#t5;xDo$gY5`Q=Ong z_H?aMg(O%C1`s6c4)l!}-W*Co)RXrzWLrQoDBuaUP>>|L&SllO56QNGR=P%FPvNqBC4W`sA^w0xe!oQbP-G80D@$_26hxi zS84mg$+Un+O2b`M(M5=2_aT`UaI5v+9rmHGgCazqyqCOY_W7hin=F1ykPy))?`6ov zV#57p(p2EY6-a^Hti~i3QQ#jA#vxbBSxH1R70y1~zBF24mO@v&uF<}U_II$mH6CwAvH3giQT6~e*3y6e@nBdVh5e|ibNRWtWwJ)4Q zBOu}xG0pacbEpJFJR&MzJa}XHw9)^+Qx+5y6cniEHS^ViYa&wE8vp { builder.close(); }); - test('mountId', async ({ page }) => { - await page.goto(getHrefByEntryName('main', builder.port)); - - const test = page.locator('#test'); - await expect(test).toHaveText('Hello Builder!'); - }); - test('title default', async ({ page }) => { await page.goto(getHrefByEntryName('main', builder.port)); await expect(page.evaluate(`document.title`)).resolves.toBe(''); }); - - test('inject default (head)', async () => { - const pagePath = join(builder.distPath, 'html/main/index.html'); - const content = await fs.readFile(pagePath, 'utf-8'); - - expect( - /[\s\S]*[\s\S]*<\/head>/.test(content), - ).toBeTruthy(); - expect( - /[\s\S]*[\s\S]*<\/body>/.test(content), - ).toBeFalsy(); - }); }); test.describe('html element set', () => { @@ -72,7 +53,6 @@ test.describe('html element set', () => { description: 'a description of the page', }, inject: 'body', - appIcon: './src/assets/icon.png', favicon: './src/assets/icon.png', }, }, @@ -92,34 +72,6 @@ test.describe('html element set', () => { builder.close(); }); - test('appicon', async () => { - const [, iconRelativePath] = - //.exec(mainContent) || []; - - expect(iconRelativePath).toBeDefined(); - - const iconPath = join(builder.distPath, iconRelativePath); - expect(fs.existsSync(iconPath)).toBeTruthy(); - - // should work on all page - expect( - //.test(fooContent), - ).toBeTruthy(); - }); - - test('favicon', async () => { - const [, iconRelativePath] = - //.exec(mainContent) || []; - - expect(iconRelativePath).toBeDefined(); - - const iconPath = join(builder.distPath, iconRelativePath); - expect(fs.existsSync(iconPath)).toBeTruthy(); - - // should work on all page - expect(//.test(fooContent)).toBeTruthy(); - }); - test('custom inject', async () => { expect( /[\s\S]*[\s\S]*<\/head>/.test(mainContent), @@ -162,40 +114,6 @@ test('custom title', async ({ page }) => { builder.close(); }); -test('template & templateParameters', async ({ page }) => { - const builder = await build({ - cwd: join(fixtures, 'template'), - entry: { - main: join(join(fixtures, 'template'), 'src/index.ts'), - }, - runServer: true, - builderConfig: { - html: { - template: './static/index.html', - templateParameters: { - foo: 'bar', - }, - }, - }, - }); - - await page.goto(getHrefByEntryName('main', builder.port)); - - await expect(page.evaluate(`document.title`)).resolves.toBe( - 'custom template', - ); - - const testTemplate = page.locator('#test-template'); - await expect(testTemplate).toHaveText('xxx'); - - const testEl = page.locator('#test'); - await expect(testEl).toHaveText('Hello Builder!'); - - await expect(page.evaluate(`window.foo`)).resolves.toBe('bar'); - - builder.close(); -}); - test('outputStructrue flat', async ({ page }) => { const builder = await build({ cwd: join(fixtures, 'template'), diff --git a/tests/e2e/builder/cases/html/inject-false/index.test.ts b/tests/e2e/builder/cases/html/inject-false/index.test.ts deleted file mode 100644 index 3c302405a060..000000000000 --- a/tests/e2e/builder/cases/html/inject-false/index.test.ts +++ /dev/null @@ -1,38 +0,0 @@ -import path from 'path'; -import { expect, test } from '@playwright/test'; -import { build } from '@scripts/shared'; - -test('builder injection script order should be as expected', async () => { - const builder = await build({ - cwd: __dirname, - entry: { index: path.resolve(__dirname, './src/index.js') }, - builderConfig: { - html: { - inject: false, - template: './static/index.html', - }, - output: { - assetsRetry: { - inlineScript: false, - }, - disableInlineRuntimeChunk: true, - convertToRem: { - inlineRuntime: false, - }, - }, - }, - }); - const files = await builder.unwrapOutputJSON(); - - const html = - files[Object.keys(files).find(file => file.endsWith('index.html'))!]; - - // assetsRetry => rem => normal resource => template custom resource - expect( - html.indexOf('/js/assets-retry') < html.indexOf('/js/convert-rem'), - ).toBeTruthy(); - expect( - html.indexOf('/js/convert-rem') < html.indexOf('/js/index'), - ).toBeTruthy(); - expect(html.indexOf('/js/index') < html.indexOf('/assets/a.js')).toBeTruthy(); -}); diff --git a/tests/e2e/builder/cases/html/inject-false/src/index.css b/tests/e2e/builder/cases/html/inject-false/src/index.css deleted file mode 100644 index fb41630886f1..000000000000 --- a/tests/e2e/builder/cases/html/inject-false/src/index.css +++ /dev/null @@ -1,3 +0,0 @@ -.test { - font-size: 14px; -} diff --git a/tests/e2e/builder/cases/html/inject-false/src/index.js b/tests/e2e/builder/cases/html/inject-false/src/index.js deleted file mode 100644 index 0a0c568f08e7..000000000000 --- a/tests/e2e/builder/cases/html/inject-false/src/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import './index.css'; - -console.log('1'); diff --git a/tests/e2e/builder/cases/html/inject-false/static/index.html b/tests/e2e/builder/cases/html/inject-false/static/index.html deleted file mode 100644 index 732b16c47547..000000000000 --- a/tests/e2e/builder/cases/html/inject-false/static/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - custom template - <%= htmlWebpackPlugin.tags.headTags %> - - - -
xxx
-
- <%= htmlWebpackPlugin.tags.bodyTags %> - - diff --git a/tests/e2e/builder/cases/html/script-loading/index.test.ts b/tests/e2e/builder/cases/html/script-loading/index.test.ts deleted file mode 100644 index e4af6bb5a7f1..000000000000 --- a/tests/e2e/builder/cases/html/script-loading/index.test.ts +++ /dev/null @@ -1,49 +0,0 @@ -import path from 'path'; -import { expect, test } from '@playwright/test'; -import { build } from '@scripts/shared'; - -test('should apply defer by default', async () => { - const builder = await build({ - cwd: __dirname, - entry: { index: path.resolve(__dirname, './src/index.js') }, - }); - const files = await builder.unwrapOutputJSON(); - const html = - files[Object.keys(files).find(file => file.endsWith('index.html'))!]; - - expect(html).toContain('