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 从项目根目录解析指定的包,这可以用于移除重复包和减少包大小。