Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/core/src/cli/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ export const applyCliOptions = (
options: BuildOptions,
root: string,
): void => {
if (config.lib === undefined) {
config.lib = [{} satisfies LibConfig];
}

if (options.root) {
config.root = root;
}
Expand Down
5 changes: 4 additions & 1 deletion packages/core/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1963,7 +1963,7 @@ export async function composeCreateRsbuildConfig(
): Promise<RsbuildConfigWithLibInfo[]> {
const constantRsbuildConfig = await createConstantRsbuildConfig();
const {
lib: libConfigsArray,
lib: rawLibConfigsArray,
mode: _mode,
root,
plugins: sharedPlugins,
Expand All @@ -1977,6 +1977,9 @@ export async function composeCreateRsbuildConfig(
logger.level = logLevel;
}

const libConfigsArray =
rawLibConfigsArray === undefined ? [{}] : rawLibConfigsArray;

if (!Array.isArray(libConfigsArray) || libConfigsArray.length === 0) {
throw new Error(
`Expect "lib" field to be a non-empty array, but got: ${color.cyan(
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/types/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ interface RslibOutputConfig extends OutputConfig {
}

export interface RslibConfig extends RsbuildConfig {
lib: LibConfig[];
lib?: LibConfig[];
/**
* @inheritdoc
*/
Expand Down
44 changes: 42 additions & 2 deletions packages/core/tests/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,46 @@ describe('parseEntryOption', () => {
});

describe('applyCliOptions', () => {
test('applies CLI flags to the implicit default library', () => {
const config = {
source: {},
output: {},
} as RslibConfig;

const options = {
format: 'cjs',
entry: ['index=src/index.ts'],
dts: true,
} as CommonOptions;

applyCliOptions(config, options, '/abs/root');

expect(config.lib).toEqual([
{
dts: true,
format: 'cjs',
output: {},
source: {
entry: {
index: 'src/index.ts',
},
},
},
]);
});

test('does not apply CLI flags to null lib field as implicit default library', () => {
const config = {
lib: null,
} as unknown as RslibConfig;

const options = {
format: 'cjs',
} as CommonOptions;

expect(() => applyCliOptions(config, options, '/abs/root')).toThrow();
});

test('applies CLI flags to the config and its libraries', () => {
const config = {
root: '/initial',
Expand Down Expand Up @@ -117,15 +157,15 @@ describe('applyCliOptions', () => {
distPath: 'dist/custom',
} as CommonOptions;

const libBefore = config.lib[0]!;
const libBefore = config.lib![0]!;
const outputBefore = libBefore.output;

applyCliOptions(config, options, '/abs/custom');

expect(config.root).toBe('/abs/custom');
expect(config.logLevel).toBe('error');

const lib = config.lib[0]!;
const lib = config.lib![0]!;
expect(lib.format).toBe('cjs');
expect(lib.bundle).toBe(false);
expect(lib.dts).toBe(true);
Expand Down
24 changes: 24 additions & 0 deletions packages/core/tests/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,30 @@ describe('CLI options', () => {
});

describe('Should compose create Rsbuild config correctly', () => {
test('treats omitted lib field as default library config', async () => {
const rslibConfig: RslibConfig = {
root: join(__dirname, '..'),
};

const composedRsbuildConfig = await composeRsbuildEnvironments(rslibConfig);

expect(Object.keys(composedRsbuildConfig.environments))
.toMatchInlineSnapshot(`
[
"esm",
]
`);
expect(composedRsbuildConfig.environmentWithInfos[0]?.format).toBe('esm');
});

test('does not treat null lib field as default library config', async () => {
const rslibConfig = {
lib: null,
} as unknown as RslibConfig;

await expect(composeCreateRsbuildConfig(rslibConfig)).rejects.toThrow();
});

test('Merge Rsbuild config in each format', async () => {
const rslibConfig: RslibConfig = {
lib: [
Expand Down
6 changes: 3 additions & 3 deletions packages/core/tests/exe.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import {

const packageRoot = path.resolve(import.meta.dirname, '..');

type TestLibConfig = Parameters<
typeof composeCreateRsbuildConfig
>[0]['lib'][number];
type TestLibConfig = NonNullable<
Parameters<typeof composeCreateRsbuildConfig>[0]['lib']
>[number];

const composeTestRslibConfig = (lib: TestLibConfig) =>
composeCreateRsbuildConfig({
Expand Down
7 changes: 4 additions & 3 deletions tests/benchmark/index.bench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ const disableDts = (rslibConfig: RslibConfig) => {
};

const onlyEnableMF = (rslibConfig: RslibConfig) => {
const length = rslibConfig.lib.length;
const lib = rslibConfig.lib!;
const length = lib.length;
for (let i = length - 1; i >= 0; i--) {
if (rslibConfig.lib[i] && rslibConfig.lib[i]!.format !== 'mf') {
rslibConfig.lib.splice(i, 1);
if (lib[i] && lib[i]!.format !== 'mf') {
lib.splice(i, 1);
}
}
disableDts(rslibConfig);
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/shims/esm/rslibShimsDisabled.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import config from './rslib.config';

export default defineConfig({
...config,
lib: config.lib.map((libConfig) => {
lib: config.lib!.map((libConfig) => {
if (typeof libConfig.output!.distPath === 'string') {
libConfig.output!.distPath = libConfig.output!.distPath.replace(
'./dist/enabled',
Expand Down
4 changes: 2 additions & 2 deletions tests/scripts/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,15 +164,15 @@ export async function getResults(
let mfExposeEntry: string | undefined;
let key = '';

const formatCount: Record<Format, number> = rslibConfig.lib.reduce(
const formatCount: Record<Format, number> = rslibConfig.lib!.reduce(
(acc, { format = 'esm' }) => {
acc[format] = (acc[format] ?? 0) + 1;
return acc;
},
{} as Record<Format, number>,
);

for (const libConfig of rslibConfig.lib) {
for (const libConfig of rslibConfig.lib!) {
const { format = 'esm' } = libConfig;
const currentFormatCount = formatCount[format];
const currentFormatIndex = formatIndex[format]++;
Expand Down
10 changes: 10 additions & 0 deletions tests/type-tests/resolution-bundler/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,13 @@ import { createRslib, defineConfig } from '@rslib/core';
createRslib({});

defineConfig({ lib: [] });

defineConfig({});

defineConfig({
source: {
entry: {
index: './src/index.ts',
},
},
});
10 changes: 10 additions & 0 deletions tests/type-tests/resolution-nodenext/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,13 @@ import { createRslib, defineConfig } from '@rslib/core';
createRslib({});

defineConfig({ lib: [] });

defineConfig({});

defineConfig({
source: {
entry: {
index: './src/index.ts',
},
},
});
8 changes: 5 additions & 3 deletions website/docs/en/config/lib/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ interface LibConfig extends EnvironmentConfig {
}

interface RslibConfig extends RsbuildConfig {
lib: LibConfig[];
lib?: LibConfig[];
}
```

- **Default:** `undefined`
- **Default:** `[{}]`

- **Required:** `true`
- **Required:** `false`

The `lib` configuration is an array of objects, each representing a distinct set of configurations. These include all Rsbuild configurations as well as Rslib-specific configurations, designed to generate different outputs.

If `lib` is omitted, Rslib uses a default configuration equivalent to `lib: [{}]`; if `lib` is set explicitly, it must be a non-empty array.
2 changes: 2 additions & 0 deletions website/docs/en/guide/basic/configure-rslib.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Rslib's configuration is based on Rsbuild, which means that you can use all of R

Rslib provides the `lib` option to configure the library outputs. It is an array, and each object is used to describe a format of the output.

When you only need the default single ESM output, you can omit the `lib` field. This is equivalent to setting `lib: [{}]`.

For example, output ESM and CJS formats, and use `es2021` syntax:

```js title="rslib.config.mjs"
Expand Down
8 changes: 5 additions & 3 deletions website/docs/zh/config/lib/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ interface LibConfig extends EnvironmentConfig {
}

interface RslibConfig extends RsbuildConfig {
lib: LibConfig[];
lib?: LibConfig[];
}
```

- **默认值:** `undefined`
- **默认值:** `[{}]`

- **必选:** `true`
- **必选:** `false`

`lib` 配置是一个对象数组,每个对象代表一组不同的配置。这些配置包括所有 Rsbuild 配置以及 Rslib 特定的配置,可以生成不同格式的产物。

若省略 `lib` 字段,Rslib 会使用等价于 `lib: [{}]` 的默认配置;若显式配置 `lib`,则必须为非空数组。
2 changes: 2 additions & 0 deletions website/docs/zh/guide/basic/configure-rslib.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Rslib 的配置是基于 Rsbuild 扩展的,这意味着你可以使用 Rsbuild

Rslib 提供了 `lib` 选项来配置库产物,它是一个数组,每个对象用于描述一种输出格式。

当你只需要默认的单个 ESM 产物时,可以省略 `lib` 字段。这等价于配置 `lib: [{}]`。

例如,输出 ESM 和 CJS 两种格式的产物,并使用 `es2021` 语法:

```js title="rslib.config.mjs"
Expand Down