Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: autoExternal default to false when format is umd or mf #531

Merged
merged 3 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
29 changes: 23 additions & 6 deletions packages/core/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import {
color,
getAbsolutePath,
isEmptyObject,
isIntermediateOutputFormat,
isObject,
nodeBuiltInModules,
omit,
Expand Down Expand Up @@ -234,14 +235,29 @@ const composeExternalsWarnConfig = (
};
};

const getAutoExternalDefaultValue = (
format: Format,
autoExternal?: AutoExternal,
): AutoExternal => {
return isIntermediateOutputFormat(format)
? (autoExternal ?? true)
: (autoExternal ?? false);
Timeless0911 marked this conversation as resolved.
Show resolved Hide resolved
};

export const composeAutoExternalConfig = (options: {
autoExternal: AutoExternal;
format: Format;
autoExternal?: AutoExternal;
pkgJson?: PkgJson;
userExternals?: NonNullable<RsbuildConfig['output']>['externals'];
}): RsbuildConfig => {
const { autoExternal, pkgJson, userExternals } = options;
const { format, pkgJson, userExternals } = options;

if (!autoExternal) {
const autoExternal = getAutoExternalDefaultValue(
format,
options.autoExternal,
);

if (autoExternal === false) {
return {};
}

Expand Down Expand Up @@ -1005,7 +1021,7 @@ const composeDtsConfig = async (
libConfig: LibConfig,
dtsExtension: string,
): Promise<RsbuildConfig> => {
const { autoExternal, banner, footer } = libConfig;
const { format, autoExternal, banner, footer } = libConfig;

let { dts } = libConfig;

Expand All @@ -1028,7 +1044,7 @@ const composeDtsConfig = async (
build: dts?.build,
abortOnError: dts?.abortOnError,
dtsExtension: dts?.autoExtension ? dtsExtension : '.d.ts',
autoExternal,
autoExternal: getAutoExternalDefaultValue(format!, autoExternal),
banner: banner?.dts,
footer: footer?.dts,
}),
Expand Down Expand Up @@ -1150,7 +1166,7 @@ async function composeLibRsbuildConfig(config: LibConfig) {
banner = {},
footer = {},
autoExtension = true,
autoExternal = true,
autoExternal,
externalHelpers = false,
redirect = {},
umdName,
Expand Down Expand Up @@ -1190,6 +1206,7 @@ async function composeLibRsbuildConfig(config: LibConfig) {
);
const syntaxConfig = composeSyntaxConfig(target, config?.syntax);
const autoExternalConfig = composeAutoExternalConfig({
format: format!,
autoExternal,
pkgJson,
userExternals: config.output?.externals,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/types/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export interface LibConfig extends RsbuildConfig {
autoExtension?: boolean;
/**
* Whether to automatically externalize dependencies of different dependency types and do not bundle them.
* @defaultValue `true`
* @defaultValue `true` when {@link format} is `cjs` or `esm`, `false` when {@link format} is `umd` or `mf`.
* @see {@link https://lib.rsbuild.dev/config/lib/auto-external}
*/
autoExternal?: AutoExternal;
Expand Down
6 changes: 5 additions & 1 deletion packages/core/src/utils/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import path, { isAbsolute, join } from 'node:path';
import type { RsbuildPlugins } from '@rsbuild/core';
import color from 'picocolors';

import type { LibConfig, PkgJson } from '../types';
import type { Format, LibConfig, PkgJson } from '../types';
import { logger } from './logger';

/**
Expand Down Expand Up @@ -232,4 +232,8 @@ export const isTTY = (type: 'stdin' | 'stdout' = 'stdout'): boolean => {
);
};

export const isIntermediateOutputFormat = (format: Format): boolean => {
return format === 'cjs' || format === 'esm';
};

export { color };
128 changes: 128 additions & 0 deletions packages/core/tests/external.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,83 @@ import { composeAutoExternalConfig } from '../src/config';
vi.mock('rslog');

describe('should composeAutoExternalConfig correctly', () => {
it('autoExternal default value', () => {
const esmResult = composeAutoExternalConfig({
format: 'esm',
autoExternal: undefined,
pkgJson: {
name: 'esm',
dependencies: {
foo: '1.0.0',
},
},
});

const cjsResult = composeAutoExternalConfig({
format: 'cjs',
autoExternal: undefined,
pkgJson: {
name: 'cjs',
dependencies: {
foo: '1.0.0',
},
},
});

const umdResult = composeAutoExternalConfig({
format: 'umd',
autoExternal: undefined,
pkgJson: {
name: 'umd',
dependencies: {
foo: '1.0.0',
},
},
});

const mfResult = composeAutoExternalConfig({
format: 'mf',
autoExternal: undefined,
pkgJson: {
name: 'mf',
dependencies: {
foo: '1.0.0',
},
},
});

expect(esmResult).toMatchInlineSnapshot(`
{
"output": {
"externals": [
/\\^foo\\(\\$\\|\\\\/\\|\\\\\\\\\\)/,
"foo",
],
},
}
`);

expect(cjsResult).toMatchInlineSnapshot(`
{
"output": {
"externals": [
/\\^foo\\(\\$\\|\\\\/\\|\\\\\\\\\\)/,
"foo",
],
},
}
`);

expect(umdResult).toMatchInlineSnapshot('{}');
expect(mfResult).toMatchInlineSnapshot('{}');
});

it('autoExternal is true', () => {
const result = composeAutoExternalConfig({
format: 'esm',
autoExternal: true,
pkgJson: {
name: 'esm',
dependencies: {
foo: '1.0.0',
foo1: '1.0.0',
Expand Down Expand Up @@ -35,10 +108,58 @@ describe('should composeAutoExternalConfig correctly', () => {
});
});

it('autoExternal is true when format is umd or mf', () => {
const umdResult = composeAutoExternalConfig({
format: 'umd',
autoExternal: true,
pkgJson: {
name: 'umd',
dependencies: {
foo: '1.0.0',
},
},
});

expect(umdResult).toMatchInlineSnapshot(`
{
"output": {
"externals": [
/\\^foo\\(\\$\\|\\\\/\\|\\\\\\\\\\)/,
"foo",
],
},
}
`);

const mfResult = composeAutoExternalConfig({
format: 'mf',
autoExternal: true,
pkgJson: {
name: 'mf',
dependencies: {
foo: '1.0.0',
},
},
});

expect(mfResult).toMatchInlineSnapshot(`
{
"output": {
"externals": [
/\\^foo\\(\\$\\|\\\\/\\|\\\\\\\\\\)/,
"foo",
],
},
}
`);
});

it('autoExternal will deduplication ', () => {
const result = composeAutoExternalConfig({
format: 'esm',
autoExternal: true,
pkgJson: {
name: 'esm',
dependencies: {
foo: '1.0.0',
foo1: '1.0.0',
Expand Down Expand Up @@ -70,11 +191,13 @@ describe('should composeAutoExternalConfig correctly', () => {

it('autoExternal is object', () => {
const result = composeAutoExternalConfig({
format: 'esm',
autoExternal: {
peerDependencies: false,
devDependencies: true,
},
pkgJson: {
name: 'esm',
dependencies: {
foo: '1.0.0',
},
Expand All @@ -96,8 +219,10 @@ describe('should composeAutoExternalConfig correctly', () => {

it('autoExternal is false', () => {
const result = composeAutoExternalConfig({
format: 'esm',
autoExternal: false,
pkgJson: {
name: 'esm',
dependencies: {
foo: '1.0.0',
},
Expand All @@ -109,8 +234,10 @@ describe('should composeAutoExternalConfig correctly', () => {

it('autoExternal with user externals object', () => {
const result = composeAutoExternalConfig({
format: 'esm',
autoExternal: true,
pkgJson: {
name: 'esm',
dependencies: {
foo: '1.0.0',
bar: '1.0.0',
Expand All @@ -130,6 +257,7 @@ describe('should composeAutoExternalConfig correctly', () => {

it('read package.json failed', () => {
const result = composeAutoExternalConfig({
format: 'esm',
autoExternal: true,
});

Expand Down
3 changes: 3 additions & 0 deletions tests/integration/umd-library-name/rslib.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,8 @@ export default defineConfig({
},
output: {
target: 'web',
externals: {
react: 'react',
},
},
});
4 changes: 3 additions & 1 deletion website/docs/en/config/lib/auto-external.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ type AutoExternal =
};
```

- **Default:** `true`
- **Default:**
- `true` when [format](/config/lib/format) is `cjs` or `esm`
- `false` when [format](/config/lib/format) is `umd` or `mf`

Whether to automatically externalize dependencies of different dependency types and do not bundle them.

Expand Down
2 changes: 1 addition & 1 deletion website/docs/en/guide/advanced/third-party-deps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ In addition to `"dependencies"`, `"peerDependencies"`can also declare dependenci

## Default handling of third-party dependencies

By default, third-party dependencies under `"dependencies"`, `"optionalDependencies"` and `"peerDependencies"` are not bundled by Rslib.
By default, when generating CJS or ESM outputs, third-party dependencies under `"dependencies"`, `"optionalDependencies"` and `"peerDependencies"` are not bundled by Rslib.

This is because when the npm package is installed, its `"dependencies"` will also be installed. By not packaging `"dependencies"`, you can reduce the size of the package product.

Expand Down
4 changes: 3 additions & 1 deletion website/docs/zh/config/lib/auto-external.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ type AutoExternal =
};
```

- **默认值:** `true`
- **默认值:**
- 当 [format](/config/lib/format) 为 `cjs` 或 `esm` 时为 `true`
- 当 [format](/config/lib/format) 为 `umd` 或 `mf` 时为 `false`

是否自动对不同依赖类型的依赖进行外部化处理,不将其打包。

Expand Down
2 changes: 1 addition & 1 deletion website/docs/zh/guide/advanced/third-party-deps.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

## 三方依赖的默认处理

默认情况下,`dependencies`、`optionalDependencies` 和 `peerDependencies` 字段下的三方依赖不会被 Rslib 打包。
默认情况下,当生成 CJS 或 ESM 产物时,`dependencies`、`optionalDependencies` 和 `peerDependencies` 字段下的三方依赖不会被 Rslib 打包。

这是因为在 npm 包安装时,其 `dependencies` 也会被安装。通过不打包 `dependencies`,可以减少包的体积。

Expand Down
Loading