Skip to content
Merged
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: 2 additions & 2 deletions e2e/cases/externals/node/rslib.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { generateBundleCjsConfig, generateBundleEsmConfig } from '#shared';

export default defineConfig({
lib: [
generateBundleEsmConfig(__dirname, { platform: 'node' }),
generateBundleCjsConfig(__dirname, { platform: 'node' }),
generateBundleEsmConfig(__dirname, { output: { target: 'node' } }),
generateBundleCjsConfig(__dirname, { output: { target: 'node' } }),
],
source: {
entry: {
Expand Down
93 changes: 55 additions & 38 deletions packages/core/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import { DEFAULT_CONFIG_NAME, DEFAULT_EXTENSIONS } from './constant';
import type {
Format,
LibConfig,
Platform,
RslibConfig,
RslibConfigAsyncFn,
RslibConfigExport,
RslibConfigSyncFn,
Syntax,
} from './types/config';
import { getDefaultExtension } from './utils/extension';
import { color } from './utils/helper';
Expand Down Expand Up @@ -155,27 +155,6 @@ const getDefaultFormatConfig = (format: Format): RsbuildConfig => {
}
};

const getDefaultPlatformConfig = (platform: Platform): RsbuildConfig => {
switch (platform) {
case 'browser':
return {};
case 'node':
return {
output: {
// When output.target is 'node', Node.js's built-in will be treated as externals of type `node-commonjs`.
// Simply override the built-in modules to make them external.
// https://github.com/webpack/webpack/blob/dd44b206a9c50f4b4cb4d134e1a0bd0387b159a3/lib/node/NodeTargetPlugin.js#L81
externals: nodeBuiltInModules,
target: 'node',
},
};
case 'neutral':
return {};
default:
throw new Error(`Unsupported platform: ${platform}`);
}
};

const getDefaultAutoExtensionConfig = (
format: Format,
root: string,
Expand All @@ -196,33 +175,61 @@ const getDefaultAutoExtensionConfig = (
};
};

const getDefaultSyntax = (_syntax?: Syntax): RsbuildConfig => {
return {};
};

export function convertLibConfigToRsbuildConfig(
libConfig: LibConfig,
rsbuildConfig: RsbuildConfig,
configPath: string,
): RsbuildConfig {
const { format, platform = 'browser', autoExtension = false } = libConfig;
const { format, autoExtension = false } = libConfig;

const formatConfig = getDefaultFormatConfig(format!);
const platformConfig = getDefaultPlatformConfig(platform);
const autoExtensionConfig = getDefaultAutoExtensionConfig(
format!,
dirname(rsbuildConfig._privateMeta?.configFilePath ?? process.cwd()),
dirname(configPath),
autoExtension,
);
const syntaxConfig = getDefaultSyntax(libConfig.output?.syntax);

return mergeRsbuildConfig(formatConfig, autoExtensionConfig, syntaxConfig);
}

return mergeRsbuildConfig(
rsbuildConfig,
formatConfig,
platformConfig,
autoExtensionConfig,
function postUpdateRsbuildConfig(rsbuildConfig: RsbuildConfig) {
const defaultTargetConfig = getDefaultTargetConfig(
rsbuildConfig.output?.target ?? 'web',
);

return mergeRsbuildConfig(defaultTargetConfig);
}

const getDefaultTargetConfig = (target: string): RsbuildConfig => {
switch (target) {
case 'web':
return {};
case 'node':
return {
output: {
// When output.target is 'node', Node.js's built-in will be treated as externals of type `node-commonjs`.
// Simply override the built-in modules to make them external.
// https://github.com/webpack/webpack/blob/dd44b206a9c50f4b4cb4d134e1a0bd0387b159a3/lib/node/NodeTargetPlugin.js#L81
externals: nodeBuiltInModules,
target: 'node',
},
};
case 'neutral':
return {};
default:
throw new Error(`Unsupported platform: ${target}`);
}
};

export async function composeCreateRsbuildConfig(
rslibConfig: RslibConfig,
): Promise<Partial<Record<Format, RsbuildConfig>>> {
const internalRsbuildConfig = await createInternalRsbuildConfig();

const configPath = rslibConfig._privateMeta?.configFilePath ?? process.cwd();
const { lib: libConfigsArray, ...sharedRsbuildConfig } = rslibConfig;

if (!libConfigsArray) {
Expand All @@ -234,19 +241,29 @@ export async function composeCreateRsbuildConfig(
const composedRsbuildConfig: Partial<Record<Format, RsbuildConfig>> = {};

for (const libConfig of libConfigsArray) {
const { format, platform, ...overrideRsbuildConfig } = libConfig;
const { format, ...overrideRsbuildConfig } = libConfig;

const libConvertedRsbuildConfig = convertLibConfigToRsbuildConfig(
libConfig,
configPath,
);

// Merge order matters, keep `internalRsbuildConfig` at the last position
// to ensure that the internal config is not overridden by the user's config.
const mergedRsbuildConfig = mergeRsbuildConfig(
sharedRsbuildConfig,
overrideRsbuildConfig,
internalRsbuildConfig,
libConvertedRsbuildConfig,
);

composedRsbuildConfig[format!] = convertLibConfigToRsbuildConfig(
libConfig,
// Some configurations can be defined both in the shared config and the lib config.
// So we need to do the post process after lib config is converted and merged.
const postUpdatedConfig = postUpdateRsbuildConfig(mergedRsbuildConfig);

composedRsbuildConfig[format!] = mergeRsbuildConfig(
mergedRsbuildConfig,
postUpdatedConfig,
// Merge order matters, keep `internalRsbuildConfig` at the last position
// to ensure that the internal config is not overridden by user's config.
internalRsbuildConfig,
);
}

Expand Down
30 changes: 28 additions & 2 deletions packages/core/src/types/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,38 @@
import type { RsbuildConfig } from '@rsbuild/core';

export type Format = 'esm' | 'cjs' | 'umd';
export type Platform = 'node' | 'browser' | 'neutral';

export type EcmaScriptVersion =
| 'esnext'
| 'es5'
| 'es6'
| 'es2015'
| 'es2016'
| 'es2017'
| 'es2018'
| 'es2019'
| 'es2020'
| 'es2021'
| 'es2022'
| 'es2023'
| 'es2024';

export type Syntax =
// Use browserslist config file
| 'browserslist'
// ECMAScript versions as an common used addition to browserslist query
| EcmaScriptVersion
| EcmaScriptVersion[]
// Support inline browserslist query, like defined in package.json
| string[];

export interface LibConfig extends RsbuildConfig {
format?: Format;
platform?: Platform;
autoExtension?: boolean;
output?: RsbuildConfig['output'] & {
/** Support esX and browserslist query */
syntax?: Syntax;
};
}

export interface RslibConfig extends RsbuildConfig {
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/utils/browserslist.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { EcmaScriptVersion } from '../types/config';

export const esVersionToBrowserList = (
_esVersion: EcmaScriptVersion,
): string[] => {
// TODO: transform esX to browserslist
return [];
};