From 3b6351082b6145c0303fc1890f25d088ba9cfb1d Mon Sep 17 00:00:00 2001 From: Timeless0911 <1604889533@qq.com> Date: Thu, 19 Dec 2024 16:32:54 +0800 Subject: [PATCH] test: add alias replace externals tests in bundleless mode --- .../alias/__snapshots__/index.test.ts.snap | 19 ++++++ tests/integration/alias/index.test.ts | 41 ++++++++++--- tests/integration/alias/rslib.config.ts | 58 +++++++++++++++++-- tests/integration/redirect/js.test.ts | 33 ++++++++++- tests/integration/redirect/js/rslib.config.ts | 39 +++++++++++-- website/docs/en/config/lib/redirect.mdx | 4 ++ website/docs/en/config/rsbuild/resolve.mdx | 12 ++-- website/docs/zh/config/lib/redirect.mdx | 4 ++ website/docs/zh/config/rsbuild/resolve.mdx | 12 ++-- 9 files changed, 196 insertions(+), 26 deletions(-) diff --git a/tests/integration/alias/__snapshots__/index.test.ts.snap b/tests/integration/alias/__snapshots__/index.test.ts.snap index 58f259b31..ee0ddabf5 100644 --- a/tests/integration/alias/__snapshots__/index.test.ts.snap +++ b/tests/integration/alias/__snapshots__/index.test.ts.snap @@ -18,3 +18,22 @@ if (__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_targe }); " `; + +exports[`source.alias 3`] = ` +"import * as __WEBPACK_EXTERNAL_MODULE__a_js__ from "./a.js"; +console.info(__WEBPACK_EXTERNAL_MODULE__a_js__.a); +" +`; + +exports[`source.alias 4`] = ` +""use strict"; +var __webpack_exports__ = {}; +const external_a_cjs_namespaceObject = require("./a.cjs"); +console.info(external_a_cjs_namespaceObject.a); +var __webpack_export_target__ = exports; +for(var __webpack_i__ in __webpack_exports__)__webpack_export_target__[__webpack_i__] = __webpack_exports__[__webpack_i__]; +if (__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_target__, '__esModule', { + value: true +}); +" +`; diff --git a/tests/integration/alias/index.test.ts b/tests/integration/alias/index.test.ts index c07d1869c..331423b9b 100644 --- a/tests/integration/alias/index.test.ts +++ b/tests/integration/alias/index.test.ts @@ -1,14 +1,41 @@ -import { buildAndGetResults } from 'test-helper'; +import { buildAndGetResults, queryContent } from 'test-helper'; import { expect, test } from 'vitest'; test('source.alias', async () => { const fixturePath = __dirname; - const { entries } = await buildAndGetResults({ fixturePath }); + const { contents } = await buildAndGetResults({ fixturePath }); - expect(entries.esm).toContain('hello world'); - expect(entries.cjs).toContain('hello world'); + const { content: indexBundleEsmContent } = queryContent( + contents.esm0!, + /esm\/index\.js/, + ); + const { content: indexBundleCjsContent } = queryContent( + contents.cjs0!, + /cjs\/index\.cjs/, + ); + const { content: indexBundlelessEsmContent } = queryContent( + contents.esm1!, + /esm\/index\.js/, + ); + const { content: indexBundlelessCjsContent } = queryContent( + contents.cjs1!, + /cjs\/index\.cjs/, + ); - // simple artifacts check - expect(entries.esm).toMatchSnapshot(); - expect(entries.cjs).toMatchSnapshot(); + // bundle mode + expect(indexBundleEsmContent).toContain('hello world'); + expect(indexBundleCjsContent).toContain('hello world'); + + // bundleless mode + expect(indexBundlelessEsmContent).toContain( + 'import * as __WEBPACK_EXTERNAL_MODULE__a_js__ from "./a.js";', + ); + expect(indexBundlelessCjsContent).toContain( + 'const external_a_cjs_namespaceObject = require("./a.cjs");', + ); + + expect(indexBundleEsmContent).toMatchSnapshot(); + expect(indexBundleCjsContent).toMatchSnapshot(); + expect(indexBundlelessEsmContent).toMatchSnapshot(); + expect(indexBundlelessCjsContent).toMatchSnapshot(); }); diff --git a/tests/integration/alias/rslib.config.ts b/tests/integration/alias/rslib.config.ts index cb4546231..08447c4f0 100644 --- a/tests/integration/alias/rslib.config.ts +++ b/tests/integration/alias/rslib.config.ts @@ -2,12 +2,58 @@ import { defineConfig } from '@rslib/core'; import { generateBundleCjsConfig, generateBundleEsmConfig } from 'test-helper'; export default defineConfig({ - lib: [generateBundleEsmConfig(), generateBundleCjsConfig()], - source: { - entry: { - index: './src/index.ts', - }, - }, + lib: [ + generateBundleEsmConfig({ + source: { + entry: { + index: './src/index.ts', + }, + }, + output: { + distPath: { + root: 'dist/bundle/esm', + }, + }, + }), + generateBundleCjsConfig({ + source: { + entry: { + index: './src/index.ts', + }, + }, + output: { + distPath: { + root: 'dist/bundle/cjs', + }, + }, + }), + generateBundleEsmConfig({ + bundle: false, + source: { + entry: { + index: './src/**', + }, + }, + output: { + distPath: { + root: 'dist/bundleless/esm', + }, + }, + }), + generateBundleCjsConfig({ + bundle: false, + source: { + entry: { + index: './src/**', + }, + }, + output: { + distPath: { + root: 'dist/bundleless/cjs', + }, + }, + }), + ], resolve: { alias: { '@src': 'src', diff --git a/tests/integration/redirect/js.test.ts b/tests/integration/redirect/js.test.ts index 32009b219..1923944ef 100644 --- a/tests/integration/redirect/js.test.ts +++ b/tests/integration/redirect/js.test.ts @@ -86,9 +86,40 @@ test('redirect.js.path with user override externals', async () => { ); }); +test('redirect.js.path with user override alias', async () => { + const { content: indexContent, path: indexEsmPath } = queryContent( + contents.esm3!, + /esm\/index\.js/, + ); + const { path: indexCjsPath } = await queryContent( + contents.cjs3!, + /cjs\/index\.cjs/, + ); + + expect(indexContent).toMatchInlineSnapshot(` + "import * as __WEBPACK_EXTERNAL_MODULE_lodash__ from "lodash"; + import * as __WEBPACK_EXTERNAL_MODULE__others_bar_index_js__ from "./others/bar/index.js"; + import * as __WEBPACK_EXTERNAL_MODULE__others_foo_js__ from "./others/foo.js"; + import * as __WEBPACK_EXTERNAL_MODULE__baz_js__ from "./baz.js"; + import * as __WEBPACK_EXTERNAL_MODULE__bar_index_js__ from "./bar/index.js"; + import * as __WEBPACK_EXTERNAL_MODULE__foo_js__ from "./foo.js"; + const src_rslib_entry_ = __WEBPACK_EXTERNAL_MODULE_lodash__["default"].toUpper(__WEBPACK_EXTERNAL_MODULE__foo_js__.foo + __WEBPACK_EXTERNAL_MODULE__bar_index_js__.bar + __WEBPACK_EXTERNAL_MODULE__others_foo_js__.foo + __WEBPACK_EXTERNAL_MODULE__others_bar_index_js__.bar + __WEBPACK_EXTERNAL_MODULE__baz_js__.baz); + export { src_rslib_entry_ as default }; + " + `); + + const esmResult = await import(indexEsmPath); + const cjsResult = await import(indexCjsPath); + + expect(esmResult.default).toEqual(cjsResult.default); + expect(esmResult.default).toMatchInlineSnapshot( + `"FOOBAR1OTHERFOOOTHERBAR2BAZ"`, // cspell:disable-line + ); +}); + test('redirect.js.extension: false', async () => { const { content: indexContent } = queryContent( - contents.esm3!, + contents.esm4!, /esm\/index\.js/, ); expect(indexContent).toMatchInlineSnapshot(` diff --git a/tests/integration/redirect/js/rslib.config.ts b/tests/integration/redirect/js/rslib.config.ts index 57f655801..dc4f8bb2e 100644 --- a/tests/integration/redirect/js/rslib.config.ts +++ b/tests/integration/redirect/js/rslib.config.ts @@ -51,13 +51,13 @@ export default defineConfig({ generateBundleEsmConfig({ bundle: false, output: { + distPath: { + root: 'dist/js-path-externals-override/esm', + }, externals: { '@/foo': './others/foo.js', '@/bar': './others/bar/index.js', }, - distPath: { - root: 'dist/js-path-externals-override/esm', - }, }, }), generateBundleCjsConfig({ @@ -72,7 +72,38 @@ export default defineConfig({ }, }, }), - // 3 js.extension: false + // 3 js.path with user override alias + generateBundleEsmConfig({ + bundle: false, + resolve: { + alias: { + '@/foo': './src/others/foo', + '@/bar': './src/others/bar', + }, + aliasStrategy: 'prefer-alias', + }, + output: { + distPath: { + root: 'dist/js-path-alias-override/esm', + }, + }, + }), + generateBundleCjsConfig({ + bundle: false, + resolve: { + alias: { + '@/foo': './src/others/foo', + '@/bar': './src/others/bar', + }, + aliasStrategy: 'prefer-alias', + }, + output: { + distPath: { + root: 'dist/js-path-alias-override/cjs', + }, + }, + }), + // 4 js.extension: false generateBundleEsmConfig({ bundle: false, output: { diff --git a/website/docs/en/config/lib/redirect.mdx b/website/docs/en/config/lib/redirect.mdx index b48437afe..b055b700f 100644 --- a/website/docs/en/config/lib/redirect.mdx +++ b/website/docs/en/config/lib/redirect.mdx @@ -1,3 +1,7 @@ +--- +overviewHeaders: [2, 3] +--- + # lib.redirect :::info diff --git a/website/docs/en/config/rsbuild/resolve.mdx b/website/docs/en/config/rsbuild/resolve.mdx index 9d692e163..8afdce8d5 100644 --- a/website/docs/en/config/rsbuild/resolve.mdx +++ b/website/docs/en/config/rsbuild/resolve.mdx @@ -12,9 +12,9 @@ Control the priority between the `paths` option in `tsconfig.json` and the `reso Create aliases to import or require certain modules, same as the [resolve.alias](https://rspack.dev/config/resolve#resolvealias) config of Rspack. -It is important to note that `resolve.alias` differs from [output.externals](/config/rsbuild/output#outputexternals) in the following ways: +It is worth noting that in bundle mode, both `resolve.alias` and [output.externals](/config/rsbuild/output#outputexternals) can be used to set aliases, but they differ in the following ways: -- `resolve.alias` allows you to replace the target module you want to include in the output bundles with another module. It only works if [lib.bundle](/config/lib/bundle) is set to `true`. +- `resolve.alias` is used to replace the target module with another module, which will be bundled into the output. For example, if you want to replace `lodash` with `lodash-es` when bundling a package, you can configure it as follows: @@ -29,11 +29,11 @@ It is important to note that `resolve.alias` differs from [output.externals](/co }; ``` - All `lodash` modules imported in the source code will be mapped to `lodash-es` and be bundled into the output. + Now, all `lodash` imports in the source code will be mapped to `lodash-es` and bundled into the output. - `output.externals` is used to handle alias mapping for externalized modules. Externalized modules are not included in the bundle; instead, they are imported from external sources at runtime. - For example, if you want to replace `react` and `react-dom` with `preact/compat` in the bundle, you can configure it as follows: + For example, if you want to replace externalized modules `react` and `react-dom` with `preact/compat` in the bundle, you can configure it as follows: ```ts title="rslib.config.ts" export default { @@ -49,6 +49,10 @@ It is important to note that `resolve.alias` differs from [output.externals](/co Now, the code `import { useState } from 'react'` will be replaced with `import { useState } from 'preact/compat'`. +::: note +In bundleless mode, since there is no bundling concept, all modules will be externalized, so we will automatically replace the aliases in `resolve.alias` with `output.externals` to ensure the final output is generated correctly. +::: + ## resolve.dedupe Force Rsbuild to resolve the specified packages from project root, which is useful for deduplicating packages and reducing the bundle size. diff --git a/website/docs/zh/config/lib/redirect.mdx b/website/docs/zh/config/lib/redirect.mdx index e2bf63a84..f62cb8525 100644 --- a/website/docs/zh/config/lib/redirect.mdx +++ b/website/docs/zh/config/lib/redirect.mdx @@ -1,3 +1,7 @@ +--- +overviewHeaders: [2, 3] +--- + # lib.redirect :::info diff --git a/website/docs/zh/config/rsbuild/resolve.mdx b/website/docs/zh/config/rsbuild/resolve.mdx index 17dd46a55..1d17e194a 100644 --- a/website/docs/zh/config/rsbuild/resolve.mdx +++ b/website/docs/zh/config/rsbuild/resolve.mdx @@ -12,9 +12,9 @@ import { RsbuildDocBadge } from '@components/RsbuildDocBadge'; 设置文件引用的别名,对应 Rspack 的 [resolve.alias](https://rspack.dev/zh/config/resolve#resolvealias) 配置。 -值得注意的是,`resolve.alias` 与 [output.externals](/config/rsbuild/output#outputexternals) 在以下方面有所不同: +值得注意的是,在 bundle 模式下,`resolve.alias` 与 [output.externals](/config/rsbuild/output#outputexternals) 都可以用于设置别名,但它们在以下方面有所不同: -- `resolve.alias` 允许你将目标模块替换为另一个模块。它仅在 [lib.bundle](/config/lib/bundle) 设置为 `true` 时有效。 +- `resolve.alias` 用于将目标模块替换为另一个模块,该模块会被打包到产物中。 例如,如果你想在打包一个 package 时将 `lodash` 替换为 `lodash-es`,可以这样配置: @@ -29,11 +29,11 @@ import { RsbuildDocBadge } from '@components/RsbuildDocBadge'; }; ``` - 所有在源代码中导入的 `lodash` 模块将被映射为 `lodash-es`,并被打包到产物中。 + 此时,所有在源代码中导入的 `lodash` 模块将被映射为 `lodash-es`,并被打包到产物中。 - `output.externals` 用于处理外部化模块的别名映射。外部化模块不会被打包到产物中,而是在运行时从外部源导入。 - 例如,如果你想在 bundle 中将 `react` 和 `react-dom` 替换为 `preact/compat`,可以这样配置: + 例如,如果你想将外部化模块 `react` 和 `react-dom` 替换为 `preact/compat`,可以这样配置: ```ts title="rslib.config.ts" export default { @@ -49,6 +49,10 @@ import { RsbuildDocBadge } from '@components/RsbuildDocBadge'; 此时,代码 `import { useState } from 'react'` 将被替换为 `import { useState } from 'preact/compat'`。 +::: note +在 bundleless 模式下,由于并没有打包这个概念,所有模块都会被外部化,因此我们会自动将 `resolve.alias` 中的别名替换为 `output.externals` 以确保最终生成正确的产物。 +::: + ## resolve.dedupe 强制 Rsbuild 从项目根目录解析指定的包,这可以用于移除重复包和减少包大小。