diff --git a/packages/core/src/cli/commands.ts b/packages/core/src/cli/commands.ts index 0949eb95b..ec551b52a 100644 --- a/packages/core/src/cli/commands.ts +++ b/packages/core/src/cli/commands.ts @@ -43,9 +43,9 @@ const applyCommonOptions = (cli: CAC) => { ) .option( '--config-loader ', - 'Set the config file loader (jiti | native)', + 'Set the config file loader (auto | jiti | native)', { - default: 'jiti', + default: 'auto', }, ) .option('--env-dir ', 'specify the directory to load `.env` files') diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts index fb3014788..1140195f1 100644 --- a/packages/core/src/config.ts +++ b/packages/core/src/config.ts @@ -119,7 +119,7 @@ const resolveConfigPath = (root: string, customConfig?: string): string => { throw new Error(`${DEFAULT_CONFIG_NAME} not found in ${root}`); }; -export type ConfigLoader = 'jiti' | 'native'; +export type ConfigLoader = 'auto' | 'jiti' | 'native'; export async function loadConfig({ cwd = process.cwd(), diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a5a6ed438..8edfbcf32 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7409,8 +7409,8 @@ packages: vscode-uri@3.0.8: resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} - vue-component-type-helpers@3.0.7: - resolution: {integrity: sha512-TvyUcFXmjZcXUvU+r1MOyn4/vv4iF+tPwg5Ig33l/FJ3myZkxeQpzzQMLMFWcQAjr6Xs7BRwVy/TwbmNZUA/4w==} + vue-component-type-helpers@3.0.8: + resolution: {integrity: sha512-WyR30Eq15Y/+odrUUMax6FmPbZwAp/HnC7qgR1r3lVFAcqwQ4wUoV79Mbh4SxDy3NiqDa+G4TOKD5xXSgBHo5A==} vue-docgen-loader@2.0.1: resolution: {integrity: sha512-myCF4O8RZTOg29tL6ki0n5zS/U1Cuf0PivrJqKdVevx3EAC4QemuveCAi+JT3L+u8vH4eXaG8H9EYefxvj4kpg==} @@ -9722,7 +9722,7 @@ snapshots: storybook: 9.1.7(@testing-library/dom@10.4.0)(prettier@3.6.2)(vite@6.3.5(@types/node@22.18.6)(jiti@2.5.1)(lightningcss@1.30.1)(sass-embedded@1.90.0)(sass@1.90.0)(stylus@0.64.0)(terser@5.43.1)(tsx@4.20.5)(yaml@2.6.1)) type-fest: 2.19.0 vue: 3.5.21(typescript@5.9.2) - vue-component-type-helpers: 3.0.7 + vue-component-type-helpers: 3.0.8 '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.28.0)': dependencies: @@ -14663,7 +14663,7 @@ snapshots: vscode-uri@3.0.8: {} - vue-component-type-helpers@3.0.7: {} + vue-component-type-helpers@3.0.8: {} vue-docgen-loader@2.0.1: dependencies: diff --git a/tests/integration/cli/build/build.test.ts b/tests/integration/cli/build/build.test.ts index d9e04c776..cd2101d47 100644 --- a/tests/integration/cli/build/build.test.ts +++ b/tests/integration/cli/build/build.test.ts @@ -82,7 +82,7 @@ describe('build command', async () => { `); }); - test('--config-loader', async () => { + test('should use Node.js native loader to load config', async () => { // Skip Node.js <= 22.18 if (!process.features.typescript) { return; @@ -103,6 +103,21 @@ describe('build command', async () => { `); }); + test('should fallback to jiti when --config-loader set to auto which is default strategy', async () => { + await fse.remove(path.join(__dirname, 'dist-auto')); + runCliSync('build --config rslib.config.auto.mts', { + cwd: __dirname, + }); + + const files = await globContentJSON(path.join(__dirname, 'dist-auto')); + const fileNames = Object.keys(files).sort(); + expect(fileNames).toMatchInlineSnapshot(` + [ + "/tests/integration/cli/build/dist-auto/index.js", + ] + `); + }); + test('--root', async () => { await fse.remove(path.join(__dirname, 'dist')); runCliSync('build --root custom-root', { diff --git a/tests/integration/cli/build/path.json b/tests/integration/cli/build/path.json new file mode 100644 index 000000000..4fcc39345 --- /dev/null +++ b/tests/integration/cli/build/path.json @@ -0,0 +1,3 @@ +{ + "distPath": "dist-auto" +} diff --git a/tests/integration/cli/build/rslib.config.auto.mts b/tests/integration/cli/build/rslib.config.auto.mts new file mode 100644 index 000000000..fca167f4a --- /dev/null +++ b/tests/integration/cli/build/rslib.config.auto.mts @@ -0,0 +1,15 @@ +import { defineConfig } from '@rslib/core'; +import { generateBundleEsmConfig } from 'test-helper'; +import distPathJson from './path.json'; + +export default defineConfig({ + lib: [ + generateBundleEsmConfig({ + output: { + distPath: { + root: distPathJson.distPath, + }, + }, + }), + ], +}); diff --git a/website/docs/en/guide/basic/cli.mdx b/website/docs/en/guide/basic/cli.mdx index a56370593..d620e69c6 100644 --- a/website/docs/en/guide/basic/cli.mdx +++ b/website/docs/en/guide/basic/cli.mdx @@ -29,7 +29,7 @@ Rslib CLI provides several common flags that can be used with all commands: | Flag | Description | | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | | `-c, --config ` | Specify the configuration file, can be a relative or absolute path, see [Specify config file](/guide/basic/configure-rslib#specify-config-file) | -| `--config-loader ` | Set the config file loader (`jiti` \| `native`), see [Specify config loader](/guide/basic/configure-rslib#specify-config-loader) | +| `--config-loader ` | Set the config file loader (`auto` \| `jiti` \| `native`), see [Specify config loader](/guide/basic/configure-rslib#specify-config-loader) | | `--env-dir ` | Specify the directory to load `.env` files, see [Rsbuild - Env directory](https://rsbuild.rs/guide/advanced/env-vars#env-directory) | | `--env-mode ` | Specify the env mode to load the `.env.[mode]` file, see [Rsbuild - Env mode](https://rsbuild.rs/guide/advanced/env-vars#env-mode) | | `-h, --help` | Display help for command | diff --git a/website/docs/en/guide/basic/configure-rslib.mdx b/website/docs/en/guide/basic/configure-rslib.mdx index cc2a75973..ecd4f1dd9 100644 --- a/website/docs/en/guide/basic/configure-rslib.mdx +++ b/website/docs/en/guide/basic/configure-rslib.mdx @@ -127,21 +127,42 @@ rslib build -c rslib.prod.config.mjs ## Specify config loader -When you use a configuration file with the `.ts`, `.mts`, and `.cts` extensions, Rslib will use [jiti](https://github.com/unjs/jiti) to load configuration files, providing interoperability between ESM and CommonJS. The behavior of module resolution differs slightly from the native behavior of Node.js. +Rslib provides three ways to load configuration files: -If your JavaScript runtime already natively supports TypeScript, you can use the `--config-loader native` option to use the Node.js native loader to load the configuration file. This can ensure that the module resolution behavior is consistent with the native behavior of Node.js and has better performance. +- `jiti`: When you use a configuration file with the `.ts`, `.mts`, and `.cts` extensions, Rslib will use [jiti](https://github.com/unjs/jiti) to load configuration files, providing interoperability between ESM and CommonJS. The behavior of module resolution differs slightly from the native behavior of Node.js. +- `native`: Use Node.js native loader to load the configuration file. This can ensure that the module resolution behavior is consistent with the native behavior of Node.js and has better performance. This requires that your JavaScript runtime already natively supports TypeScript. -For example, Node.js v22.6.0+ already natively supports TypeScript, you can use the following command to use the Node.js native loader to load the configuration file: + For example, Node.js v22.6.0+ already natively supports TypeScript, you can use the following command to use the Node.js native loader to load the configuration file: -```bash -# Node.js >= v22.18.0 -# No need to set --experimental-strip-types -npx rslib build --config-loader native + ```bash + # Node.js >= v22.18.0 + # No need to set --experimental-strip-types + npx rslib build --config-loader native -# Node.js v22.6.0 - v22.17.0 -# Need to set --experimental-strip-types -NODE_OPTIONS="--experimental-strip-types" npx rslib build --config-loader native -``` + # Node.js v22.6.0 - v22.17.1 + # Need to set --experimental-strip-types + NODE_OPTIONS="--experimental-strip-types" npx rslib build --config-loader native + ``` + +- `auto`(Default): Use Node.js's native loader to load configuration files first, fallback to using jiti if it fails. + +### About Node.js native loader + +When using Node.js's native loader, please note the following limitations: + +1. When importing JSON files, you need to use import attributes: + + ```ts + import pkgJson from './package.json' with { type: 'json' }; // ✅ Correct + import pkgJson from './package.json'; // ❌ Incorrect + ``` + +2. When importing TypeScript files, you need to include the `.ts` extension: + + ```ts + import baseConfig from './rslib.base.config.ts'; // ✅ Correct + import baseConfig from './rslib.base.config'; // ❌ Incorrect + ``` > See [Node.js - Running TypeScript Natively](https://nodejs.org/en/learn/typescript/run-natively#running-typescript-natively) for more details. diff --git a/website/docs/zh/guide/basic/cli.mdx b/website/docs/zh/guide/basic/cli.mdx index f586b3a79..ca51046df 100644 --- a/website/docs/zh/guide/basic/cli.mdx +++ b/website/docs/zh/guide/basic/cli.mdx @@ -29,7 +29,7 @@ Rslib CLI 提供了一些公共选项,可以用于所有命令: | 选项 | 描述 | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------- | | `-c, --config ` | 指定配置文件路径,可以为相对路径或绝对路径,详见 [指定配置文件](/guide/basic/configure-rslib#指定配置文件) | -| `--config-loader ` | 指定配置文件加载方式(`jiti` \| `native`),详见 [指定加载方式](/guide/basic/configure-rslib#指定加载方式) | +| `--config-loader ` | 指定配置文件加载方式(`auto` \| `jiti` \| `native`),详见 [指定加载方式](/guide/basic/configure-rslib#指定加载方式) | | `--env-dir ` | 指定目录来加载 `.env` 文件,详见 [Rsbuild - Env 目录](https://rsbuild.rs/zh/guide/advanced/env-vars#env-目录) | | `--env-mode ` | 指定 env 模式来加载 `.env.[mode]` 文件,详见 [Rsbuild - Env 模式](https://rsbuild.rs/zh/guide/advanced/env-vars#env-模式) | | `-h, --help` | 显示命令帮助 | diff --git a/website/docs/zh/guide/basic/configure-rslib.mdx b/website/docs/zh/guide/basic/configure-rslib.mdx index 1b3733d23..7bee9eec1 100644 --- a/website/docs/zh/guide/basic/configure-rslib.mdx +++ b/website/docs/zh/guide/basic/configure-rslib.mdx @@ -127,21 +127,42 @@ rslib build -c rslib.prod.config.mjs ## 指定加载方式 -当你使用 `.ts`, `.mts` 和 `.cts` 后缀的配置文件时,Rslib 会使用 [jiti](https://github.com/unjs/jiti) 来加载配置文件,提供 ESM 与 CommonJS 的互操作性,模块解析的行为与 Node.js 原生行为存在一定差异。 +Rslib 提供了三种配置文件加载方式: -如果你使用的 JavaScript 运行时已经原生支持 TypeScript,可以使用 `--config-loader native` 选项来使用 Node.js 原生 loader 来加载配置文件。这可以保证模块解析的行为与 Node.js 原生行为一致,并且性能更好。 +- `jiti`:当你使用 `.ts`, `.mts` 和 `.cts` 后缀的配置文件时,Rslib 会使用 [jiti](https://github.com/unjs/jiti) 来加载配置文件,提供 ESM 与 CommonJS 的互操作性,模块解析的行为与 Node.js 原生行为存在一定差异。 +- `native`:使用 Node.js 原生 loader 来加载配置文件,这可以保证模块解析的行为与 Node.js 原生行为一致,并且性能更好。这要求你使用的 JavaScript 运行时已经原生支持 TypeScript。 -例如,Node.js 从 v22.6.0 开始已经原生支持 TypeScript,你可以如下命令来使用 Node.js 原生 loader 来加载配置文件: + 例如,Node.js 从 v22.6.0 开始已经原生支持 TypeScript,你可以运行如下命令来使用 Node.js 原生 loader 来加载配置文件: -```bash -# Node.js >= v22.18.0 -# 不需要设置 --experimental-strip-types -npx rslib build --config-loader native + ```bash + # Node.js >= v22.18.0 + # 不需要设置 --experimental-strip-types + npx rslib build --config-loader native -# Node.js v22.6.0 - v22.17.0 -# 需要设置 --experimental-strip-types -NODE_OPTIONS="--experimental-strip-types" npx rslib build --config-loader native -``` + # Node.js v22.6.0 - v22.17.1 + # 需要设置 --experimental-strip-types + NODE_OPTIONS="--experimental-strip-types" npx rslib build --config-loader native + ``` + +- `auto`(默认):优先使用 Node.js 原生 loader 来加载配置文件,失败时回退到使用 jiti 加载。 + +### 关于 Node.js 原生 loader + +使用 Node.js 原生 loader 时,请注意以下限制: + +1. 导入 JSON 文件时,需要使用 import attributes: + + ```ts + import pkgJson from './package.json' with { type: 'json' }; // ✅ 正确 + import pkgJson from './package.json'; // ❌ 错误 + ``` + +2. 导入 TypeScript 文件时,需要包含 `.ts` 扩展名: + + ```ts + import baseConfig from './rslib.base.config.ts'; // ✅ 正确 + import baseConfig from './rslib.base.config'; // ❌ 错误 + ``` > 详见 [Node.js - Running TypeScript Natively](https://nodejs.org/en/learn/typescript/run-natively#running-typescript-natively)。