diff --git a/.changeset/mean-rice-walk.md b/.changeset/mean-rice-walk.md new file mode 100644 index 00000000..bfd3b039 --- /dev/null +++ b/.changeset/mean-rice-walk.md @@ -0,0 +1,5 @@ +--- +'@ice/pkg': major +--- + +feat: change default formats to 'esm' diff --git a/.gitignore b/.gitignore index 6f4def36..942f3a03 100644 --- a/.gitignore +++ b/.gitignore @@ -31,11 +31,13 @@ packages/*/es/ /packages/**/es /packages/**/esnext /packages/**/es2017 +/packages/**/es2022 /packages/**/cjs /packages/**/esm /packages/**/dist /tests/**/esm /tests/**/es2017 +/tests/**/es2022 /tests/**/cjs /tests/**/dist /tests/integration/**/build.config.for-test.mts @@ -45,6 +47,7 @@ packages/*/es/ examples/**/esm examples/**/es examples/**/es2017 +examples/**/es2022 examples/**/cjs examples/**/lib examples/**/dist diff --git a/packages/pkg/src/config/schema.ts b/packages/pkg/src/config/schema.ts index 7d1481e5..51211cea 100644 --- a/packages/pkg/src/config/schema.ts +++ b/packages/pkg/src/config/schema.ts @@ -52,27 +52,68 @@ export const serverSchema = z.object({ autoServeBundle: z.boolean().optional(), }); -export const userConfigSchema = z.object({ - entry: z.union([z.string(), z.string().array(), z.record(z.string(), z.string())]).optional(), - alias: z.record(z.string(), z.string()).optional(), - define: z - .record(z.string(), z.union([z.string(), z.boolean(), z.number(), z.null(), z.record(z.string(), z.any())])) - .optional(), - sourceMaps: z.union([z.boolean(), z.enum(['inline'])]).optional(), - jsxRuntime: z.enum(['classic', 'automatic']).optional(), - plugins: z.any().array().optional(), - helpers: z.enum(['external', 'inline']).optional(), - - transform: transformSchema.optional(), - bundle: bundleSchema.optional(), - declaration: z.union([ +// Shared field schemas reused across userConfigSchema and pkgUserConfigSchema +const entrySchema = z.union([z.string(), z.string().array(), z.record(z.string(), z.string())]).optional(); +const aliasSchema = z.record(z.string(), z.string()).optional(); +const defineSchema = z + .record(z.string(), z.union([z.string(), z.boolean(), z.number(), z.null(), z.record(z.string(), z.any())])) + .optional(); +const sourceMapsSchema = z.union([z.boolean(), z.enum(['inline'])]).optional(); +const jsxRuntimeSchema = z.enum(['classic', 'automatic']).optional(); +const helpersSchema = z.enum(['external', 'inline']).optional(); +const declarationSchema = z + .union([ z.boolean(), z.object({ outputMode: z.enum(['multi', 'unique']).optional(), generator: z.enum(['tsc', 'oxc']).optional(), allowJs: z.boolean().optional(), }), - ]), + ]) + .optional(); + +export const pkgUserConfigSchema = z.object({ + id: z.string().optional(), + module: z.enum(['esm', 'cjs', 'umd', 'mf']).optional(), + target: z.enum(['es5', 'es2017', 'es2022']).optional(), + bundle: z.boolean().optional(), + disable: z.boolean().optional(), + outputDir: z.string().optional(), + entryRoot: z.string().optional(), + extends: z.array(z.string()).optional(), + plugins: z.any().array().optional(), + // fields shared with bundleSchema + externals: bundleSchema.shape.externals, + name: z.string().optional(), + compileDependencies: bundleSchema.shape.compileDependencies, + polyfill: bundleSchema.shape.polyfill, + minify: bundleSchema.shape.minify, + codeSplitting: z.boolean().optional(), + engine: z.enum(['rollup', 'rslib', 'rolldown']).optional(), + // fields shared with userConfigSchema + entry: entrySchema, + alias: aliasSchema, + define: defineSchema, + jsxRuntime: jsxRuntimeSchema, + declaration: declarationSchema, + sourceMaps: sourceMapsSchema, + helpers: helpersSchema, +}); + +export const userConfigSchema = z.object({ + entry: entrySchema, + alias: aliasSchema, + define: defineSchema, + sourceMaps: sourceMapsSchema, + jsxRuntime: jsxRuntimeSchema, + plugins: z.any().array().optional(), + helpers: helpersSchema, + + // boolean | undefined is allowed to support `condition && { ... }` shorthand + pkgs: z.array(z.union([z.string(), z.boolean(), z.undefined(), pkgUserConfigSchema])).optional(), + transform: transformSchema.optional(), + bundle: bundleSchema.optional(), + declaration: declarationSchema, server: z.union([z.boolean(), serverSchema]).optional(), }); diff --git a/packages/pkg/src/config/userConfig.ts b/packages/pkg/src/config/userConfig.ts index b05800cf..df9a6c7c 100644 --- a/packages/pkg/src/config/userConfig.ts +++ b/packages/pkg/src/config/userConfig.ts @@ -1,9 +1,4 @@ -import type { TransformUserConfig } from '../types.js'; - function getUserConfig() { - const defaultTransformUserConfig: TransformUserConfig = { - formats: ['esm', 'es2017'], - }; const userConfig = [ { name: 'entry', @@ -30,11 +25,13 @@ function getUserConfig() { }, { name: 'transform', - defaultValue: defaultTransformUserConfig, }, { name: 'bundle', }, + { + name: 'pkgs', + }, ]; return userConfig; } diff --git a/packages/pkg/src/constants.ts b/packages/pkg/src/constants.ts index 88ccfebf..ea3de0bc 100644 --- a/packages/pkg/src/constants.ts +++ b/packages/pkg/src/constants.ts @@ -10,10 +10,14 @@ export const JSX_RUNTIME_SOURCE = '@ice/jsx-runtime'; export const ALIAS_TRANSFORM_FORMATS_MAP: Record = { esm: 'esm:es5', es2017: 'esm:es2017', + es2022: 'esm:es2022', cjs: 'cjs:es5', }; -export const ALIAS_BUNDLE_FORMATS_MAP: Record = { +export const ALIAS_BUNDLE_FORMATS_MAP: Record< + Exclude, + StandardBundleFormatString +> = { umd: 'umd:es5', esm: 'esm:es5', es2017: 'esm:es2017', diff --git a/packages/pkg/src/core/create.ts b/packages/pkg/src/core/create.ts index 78c99000..9d6073c0 100644 --- a/packages/pkg/src/core/create.ts +++ b/packages/pkg/src/core/create.ts @@ -6,7 +6,7 @@ import { Context, ExtendsPluginAPI, TaskConfig, UserConfig } from '../types.js'; import taskRegisterPlugin from '../plugins/component.js'; import { userConfigSchema } from '../config/schema.js'; import { createMessageBuilder, fromZodError } from 'zod-validation-error'; -import { registerPkgTasks, registerTasks } from './register.js'; +import { registerPkgTasks } from './register.js'; import { initContextTasks } from './init.js'; import { resolvePackage, runPkgPlugins } from './pkg.js'; @@ -128,15 +128,16 @@ export async function createCore(options: CreatePkgOptions) { } const pkgs = await resolvePackage(ctx); - await runPkgPlugins(ctx, pkgs); - if (pkgs.length) { - // when pkg is preset, no need to register old tasks - await registerPkgTasks(ctx, pkgs); - } else { - registerTasks(ctx); + if (pkgs.length === 0) { + throw new Error( + 'No packages were resolved. Please check your `pkgs` configuration or whether all packages have been disabled.', + ); } + await runPkgPlugins(ctx, pkgs); + registerPkgTasks(ctx, pkgs); + initContextTasks(ctx); await ctx['runCliOption'](); diff --git a/packages/pkg/src/core/init.ts b/packages/pkg/src/core/init.ts index 21600c80..b532994c 100644 --- a/packages/pkg/src/core/init.ts +++ b/packages/pkg/src/core/init.ts @@ -110,7 +110,9 @@ export function initTask(buildTask: BuildTask, options: InitTaskOptions) { // compact mode,以前的旧版本在注册任务的时候,可能不会添加 formats,则降级使用旧模式 const legacyFormats = bundleConfig.formats ?? ['esm', 'es2017']; const aliasedFormatsGroup = groupBy(legacyFormats, (format) => (format === 'es2017' ? 'es2017' : 'es5')); - const es5Formats = aliasedFormatsGroup.es5 as Array> | undefined; + const es5Formats = aliasedFormatsGroup.es5 as + | Array> + | undefined; config.formats = [...(es5Formats?.map((module) => createFormat(module, 'es5')) ?? [])]; } else { // 理论上 Pkg 模式不会出现这个情况,但为了健壮性还是尝试补上这部分 diff --git a/packages/pkg/src/core/pkg.ts b/packages/pkg/src/core/pkg.ts index d7c1c617..fce06152 100644 --- a/packages/pkg/src/core/pkg.ts +++ b/packages/pkg/src/core/pkg.ts @@ -1,6 +1,7 @@ import { AliasBundleFormatString, Context, + PresetPkg, PkgResolvedConfig, PkgUserConfig, PluginInfo, @@ -91,6 +92,19 @@ const LEGACY_PRESET_CONFIG_MAP: Record< displayId: 'umd', bundle: true, }, + es2022: { + id: 'es2022', + module: 'esm', + target: 'es2022', + outputDir: 'es2022', + }, + '!es2022': { + id: '!es2022', + module: 'esm', + target: 'es2022', + displayId: 'es2022', + bundle: true, + }, }; function parsePresetPkgString( @@ -100,7 +114,7 @@ function parsePresetPkgString( return null; } const bundle = preset[0] === '!'; - const fmtString = preset.slice(1); + const fmtString = bundle ? preset.slice(1) : preset; const fmt = tryToFormat(fmtString); if (!fmt) { // use legacy format @@ -144,8 +158,21 @@ function resolveExtends(extendsConfig: string[] = [], pkgsMap: Map `!${f}`); + const legacyPresets = [...transformPresets, ...bundlePresets]; + + // Only fall back to the default when all three config keys are absent. + // Explicitly configured empty arrays (e.g. transform.formats: []) mean + // "no legacy formats", not "nothing configured". + const hasLegacyConfig = userConfig.transform?.formats !== undefined || userConfig.bundle?.formats !== undefined; + const rawPkgs = userConfig.pkgs ?? (hasLegacyConfig || legacyPresets.length ? [] : ['esm']); + // Merge legacy presets, deduplicating against existing string entries in pkgs + const existingStrings = new Set(rawPkgs.filter((p): p is PresetPkg => typeof p === 'string')); + const pkgs = [...rawPkgs, ...(legacyPresets.filter((p) => !existingStrings.has(p)) as PresetPkg[])]; const resolvedPkgs: PkgResolvedConfig[] = []; const pkgsMap = new Map(); @@ -183,7 +210,9 @@ export async function resolvePackage(ctx: Context) { if (groupedPkgs.bundleLegacy?.length) { const formats = groupedPkgs.bundleLegacy.map((v) => v.slice(1)) as AliasBundleFormatString[]; const aliasedFormatsGroup = groupBy(formats, (format) => (format === 'es2017' ? 'es2017' : 'es5')); - const es5Formats = aliasedFormatsGroup.es5 as Array> | undefined; + const es5Formats = aliasedFormatsGroup.es5 as + | Array> + | undefined; if (es5Formats?.length) { const resolvedPkg: PkgResolvedConfig = { diff --git a/packages/pkg/src/core/register.ts b/packages/pkg/src/core/register.ts index 31018a37..fb65c519 100644 --- a/packages/pkg/src/core/register.ts +++ b/packages/pkg/src/core/register.ts @@ -1,16 +1,4 @@ -import { - AliasBundleFormatString, - Context, - BundleFormat, - TransformFormat, - TaskConfig, - TaskName, - PkgResolvedConfig, - NodeModuleType, -} from '../types.js'; -import { createFormat, isAliasFormatString, toFormat, tryToFormat } from '../helpers/formats.js'; -import { ALIAS_BUNDLE_FORMATS_MAP, ALIAS_TRANSFORM_FORMATS_MAP } from '../constants.js'; -import { groupBy } from 'es-toolkit/array'; +import { Context, TaskConfig, TaskName, PkgResolvedConfig, NodeModuleType } from '../types.js'; import { getPkgTaskName } from './pkg.js'; function createRegisterBuiltinTask(registerTask: Context['registerTask']) { @@ -22,92 +10,6 @@ function createRegisterBuiltinTask(registerTask: Context['registerTask']) { }; } -export function registerTasks(ctx: Context) { - const { userConfig, registerTask } = ctx; - const registerBuiltinTask = createRegisterBuiltinTask(registerTask); - const transformUserFormats = userConfig.transform?.formats; - let hasTransformTasks = false; - if (Array.isArray(transformUserFormats)) { - for (const format of transformUserFormats) { - hasTransformTasks = true; - if (isAliasFormatString(format, ALIAS_TRANSFORM_FORMATS_MAP)) { - const fmt = toFormat(ALIAS_TRANSFORM_FORMATS_MAP[format]); - registerBuiltinTask(`transform-${format}`, { - type: 'transform', - format: fmt, - }); - } else { - const structFormat = tryToFormat(format); - if (!structFormat) { - throw new Error(`Unknown transform format "${format}"`); - } - registerBuiltinTask(`transform-${format}`, { - type: 'transform', - format: structFormat, - }); - } - } - } - - if (userConfig.bundle) { - const groupedFormats = groupBy(userConfig.bundle?.formats ?? ['esm', 'es2017'], (format) => { - if (isAliasFormatString(format, ALIAS_BUNDLE_FORMATS_MAP)) { - return 'alias'; - } - // standard or unknow format string - return 'others'; - }); - - if (groupedFormats.alias?.length) { - const formats = groupedFormats.alias as AliasBundleFormatString[]; - const aliasedFormatsGroup = groupBy(formats, (format) => - format === 'mf' ? 'mf' : format === 'es2017' ? 'es2017' : 'es5', - ); - const es5Formats = aliasedFormatsGroup.es5 as Array> | undefined; - - if (es5Formats?.length) { - const structs: BundleFormat[] = es5Formats.map((module) => createFormat(module, 'es5')); - registerBuiltinTask(TaskName.BUNDLE_ES5, { - type: 'bundle', - formats: structs, - }); - } - - if (aliasedFormatsGroup.es2017?.length && es5Formats) { - registerBuiltinTask(TaskName.BUNDLE_ES2017, { - type: 'bundle', - formats: es5Formats.map((module) => createFormat(module, 'es2017')), - }); - } - - if (aliasedFormatsGroup.mf?.length) { - registerBuiltinTask(`bundle-mf`, { - type: 'bundle', - formats: [createFormat('mf', 'es5')], - engine: 'rslib', - }); - } - } - - for (const format of groupedFormats.others ?? []) { - const structFormat = tryToFormat(format)!; - if (!structFormat) { - throw new Error(`Unknown bundle format "${format}"`); - } - registerBuiltinTask(`bundle-${format}`, { - type: 'bundle', - formats: [structFormat], - }); - } - } - - if ((userConfig.declaration ?? true) && hasTransformTasks) { - registerBuiltinTask(TaskName.DECLARATION, { - type: 'declaration', - }); - } -} - export function registerPkgTasks(ctx: Context, pkgs: PkgResolvedConfig[]) { const { userConfig, registerTask } = ctx; const registerBuiltinTask = createRegisterBuiltinTask(registerTask); diff --git a/packages/pkg/src/engine/shared/swcConfig.ts b/packages/pkg/src/engine/shared/swcConfig.ts index 4de3b175..7b3ef0bd 100644 --- a/packages/pkg/src/engine/shared/swcConfig.ts +++ b/packages/pkg/src/engine/shared/swcConfig.ts @@ -17,11 +17,11 @@ const BROWSER_TARGETS_MAP: Record = { ios: 11, }, es2022: { - chrome: 85, - safari: 15, - firefox: 79, - edge: 85, - ios: 15, + chrome: 94, + safari: '16.4', + firefox: 93, + edge: 94, + ios: '16.4', }, }; diff --git a/packages/pkg/src/types.ts b/packages/pkg/src/types.ts index 84a8bc22..3a893fed 100644 --- a/packages/pkg/src/types.ts +++ b/packages/pkg/src/types.ts @@ -54,7 +54,7 @@ export interface Format; export type BundleFormat = Format; -export type AliasTransformFormatString = 'cjs' | 'esm' | 'es2017'; +export type AliasTransformFormatString = 'cjs' | 'esm' | 'es2017' | 'es2022'; export type AliasBundleFormatString = AliasTransformFormatString | 'umd' | 'mf'; export type TransformUserFormat = StandardTransformFormatString | AliasTransformFormatString; @@ -65,8 +65,8 @@ export interface TransformUserConfig { * Which type of contents would be generated * "cjs" - Commonjs with ES5 syntax (targeting Node version under 12); * "esm" - ES Module with ES5 syntax (legacy outputs); - * "es2017" - ES Module with ES2017 (targeting modern browsers and Node version upon 12) - * @default ['esm', 'es2017'] + * "es2017" - ES Module with ES2017 (targeting modern browsers and Node version upon 12); + * "es2022" - ES Module with ES2022 (targeting browsers supporting class static blocks+) */ formats?: TransformUserFormat[]; /** @@ -107,7 +107,6 @@ export interface BundleUserConfig { * "esm" * "cjs" * "es2017" - * @default ['esm','es2017'] */ formats?: BundleUserFormat[]; /** @@ -264,6 +263,8 @@ export interface PkgResolvedConfig export type PresetPkg = TransformUserFormat | `!${BundleUserFormat}`; export interface UserConfig { + // boolean | undefined are allowed to support `condition && { ... }` shorthand, + // where falsy values are silently ignored during resolution. pkgs?: Array; /** * Entry for a task diff --git a/packages/pkg/tests/core/pkg.test.ts b/packages/pkg/tests/core/pkg.test.ts new file mode 100644 index 00000000..24c31eba --- /dev/null +++ b/packages/pkg/tests/core/pkg.test.ts @@ -0,0 +1,142 @@ +import { describe, it, expect } from 'vitest'; +import { resolvePackage } from '../../src/core/pkg'; +import { Context, UserConfig } from '../../src'; + +function makeCtx(userConfig: Partial): Context { + return { + userConfig: { plugins: [], ...userConfig }, + rootDir: '/mock', + command: 'build', + commandArgs: {}, + extendsPluginAPI: {}, + } as unknown as Context; +} + +describe('resolvePackage', () => { + describe('默认值', () => { + it('没有任何配置时,默认输出 esm preset', async () => { + const pkgs = await resolvePackage(makeCtx({})); + expect(pkgs).toHaveLength(1); + expect(pkgs[0]).toMatchObject({ id: 'esm', module: 'esm', target: 'es5' }); + expect(pkgs[0].bundle).toBeFalsy(); + }); + + it('transform: {} 没有 formats,默认输出 esm preset', async () => { + const pkgs = await resolvePackage(makeCtx({ transform: {} })); + expect(pkgs).toHaveLength(1); + expect(pkgs[0]).toMatchObject({ id: 'esm', module: 'esm', target: 'es5' }); + }); + + it('bundle: {} 没有 formats,默认输出 esm preset', async () => { + const pkgs = await resolvePackage(makeCtx({ bundle: {} })); + expect(pkgs).toHaveLength(1); + expect(pkgs[0]).toMatchObject({ id: 'esm', module: 'esm', target: 'es5' }); + }); + + it('transform.formats: [] 显式空数组,不触发默认值,输出空数组', async () => { + const pkgs = await resolvePackage(makeCtx({ transform: { formats: [] } })); + expect(pkgs).toHaveLength(0); + }); + + it('bundle.formats: [] 显式空数组,不触发默认值,输出空数组', async () => { + const pkgs = await resolvePackage(makeCtx({ bundle: { formats: [] } })); + expect(pkgs).toHaveLength(0); + }); + }); + + describe('transform.formats 转换', () => { + it('transform.formats: ["esm"] 生成 esm+es5 产物', async () => { + const pkgs = await resolvePackage(makeCtx({ transform: { formats: ['esm'] } })); + expect(pkgs).toHaveLength(1); + expect(pkgs[0]).toMatchObject({ module: 'esm', target: 'es5' }); + expect(pkgs[0].bundle).toBeFalsy(); + }); + + it('transform.formats: ["es2017"] 生成 esm+es2017 产物', async () => { + const pkgs = await resolvePackage(makeCtx({ transform: { formats: ['es2017'] } })); + expect(pkgs).toHaveLength(1); + expect(pkgs[0]).toMatchObject({ module: 'esm', target: 'es2017' }); + }); + + it('transform.formats: ["es2022"] 生成 esm+es2022 产物', async () => { + const pkgs = await resolvePackage(makeCtx({ transform: { formats: ['es2022'] } })); + expect(pkgs).toHaveLength(1); + expect(pkgs[0]).toMatchObject({ module: 'esm', target: 'es2022' }); + }); + + it('transform.formats: ["esm", "cjs"] 生成两个产物', async () => { + const pkgs = await resolvePackage(makeCtx({ transform: { formats: ['esm', 'cjs'] } })); + expect(pkgs).toHaveLength(2); + expect(pkgs[0]).toMatchObject({ module: 'esm', target: 'es5' }); + expect(pkgs[1]).toMatchObject({ module: 'cjs', target: 'es5' }); + }); + }); + + describe('bundle.formats 转换', () => { + it('bundle.formats: ["esm"] 生成 bundle esm+es5 产物', async () => { + const pkgs = await resolvePackage(makeCtx({ bundle: { formats: ['esm'] } })); + expect(pkgs).toHaveLength(1); + expect(pkgs[0]).toMatchObject({ bundle: true, target: 'es5' }); + }); + + it('bundle.formats: ["umd"] 生成 bundle umd 产物', async () => { + const pkgs = await resolvePackage(makeCtx({ bundle: { formats: ['umd'] } })); + expect(pkgs).toHaveLength(1); + // !umd 走 bundleLegacy 路径,legacyModules 记录实际模块列表 + expect(pkgs[0]).toMatchObject({ bundle: true, target: 'es5', legacyModules: ['umd'] }); + }); + }); + + describe('pkgs + formats 合并', () => { + it('pkgs 和 transform.formats 合并', async () => { + const pkgs = await resolvePackage( + makeCtx({ + pkgs: ['cjs'], + transform: { formats: ['esm'] }, + }), + ); + expect(pkgs).toHaveLength(2); + expect(pkgs[0]).toMatchObject({ module: 'cjs', target: 'es5' }); + expect(pkgs[1]).toMatchObject({ module: 'esm', target: 'es5' }); + }); + + it('pkgs 和 bundle.formats 合并', async () => { + const pkgs = await resolvePackage( + makeCtx({ + pkgs: ['esm'], + bundle: { formats: ['umd'] }, + }), + ); + expect(pkgs).toHaveLength(2); + // bundleLegacy 优先处理,排在前面 + expect(pkgs[0]).toMatchObject({ bundle: true, target: 'es5', legacyModules: ['umd'] }); + expect(pkgs[1]).toMatchObject({ module: 'esm', target: 'es5' }); + expect(pkgs[1].bundle).toBeFalsy(); + }); + }); + + describe('去重', () => { + it('pkgs 已有的 preset,transform.formats 重复时去重', async () => { + const pkgs = await resolvePackage( + makeCtx({ + pkgs: ['esm'], + transform: { formats: ['esm', 'cjs'] }, + }), + ); + expect(pkgs).toHaveLength(2); + expect(pkgs.filter((p) => p.module === 'esm' && !p.bundle)).toHaveLength(1); + }); + + it('pkgs 已有的 bundle preset,bundle.formats 重复时去重', async () => { + const pkgs = await resolvePackage( + makeCtx({ + pkgs: ['!umd'], + bundle: { formats: ['umd'] }, + }), + ); + // !umd 已在 pkgs 中,bundle.formats: ['umd'] 产生的 '!umd' 去重后不重复添加 + expect(pkgs).toHaveLength(1); + expect(pkgs[0]).toMatchObject({ bundle: true, target: 'es5' }); + }); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e25b15cb..5c478771 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -697,6 +697,15 @@ importers: specifier: ^18.0.0 version: 18.0.15 + tests/integration/syntax-target: + dependencies: + '@ice/pkg': + specifier: workspace:* + version: link:../../../packages/pkg + '@swc/helpers': + specifier: ^0.5.15 + version: 0.5.17 + tests/integration/transform: dependencies: '@ice/pkg': diff --git a/tests/integration/default/__snapshots__/index.test.ts.snap b/tests/integration/default/__snapshots__/index.test.ts.snap index cf9ed671..db258ba4 100644 --- a/tests/integration/default/__snapshots__/index.test.ts.snap +++ b/tests/integration/default/__snapshots__/index.test.ts.snap @@ -5,7 +5,6 @@ exports[`Run config bundle > cjs structure 1`] = `null`; exports[`Run config bundle > dist structure 1`] = ` [ "dist/", - "├── index.esm.es2017.production.js", "└── index.esm.es5.production.js", ] `; @@ -52,7 +51,6 @@ exports[`Run config bundle-with-dev-mode > cjs structure 1`] = `null`; exports[`Run config bundle-with-dev-mode > dist structure 1`] = ` [ "dist/", - "├── index.esm.es2017.development.js", "└── index.esm.es5.development.js", ] `; @@ -78,8 +76,6 @@ exports[`Run config bundle-with-full-modes > cjs structure 1`] = `null`; exports[`Run config bundle-with-full-modes > dist structure 1`] = ` [ "dist/", - "├── index.esm.es2017.development.js", - "├── index.esm.es2017.production.js", "├── index.esm.es5.development.js", "└── index.esm.es5.production.js", ] @@ -93,13 +89,7 @@ exports[`Run config declaration-generator-oxc > cjs structure 1`] = `null`; exports[`Run config declaration-generator-oxc > dist structure 1`] = `null`; -exports[`Run config declaration-generator-oxc > es2017 structure 1`] = ` -[ - "es2017/", - "├── index.d.ts", - "└── index.js", -] -`; +exports[`Run config declaration-generator-oxc > es2017 structure 1`] = `null`; exports[`Run config declaration-generator-oxc > esm structure 1`] = ` [ @@ -109,18 +99,6 @@ exports[`Run config declaration-generator-oxc > esm structure 1`] = ` ] `; -exports[`Run config declaration-generator-oxc > file content es2017/index.d.ts 1`] = ` -"export declare const foo = 1; -" -`; - -exports[`Run config declaration-generator-oxc > file content es2017/index.js 1`] = ` -"const foo = 1; - -export { foo }; -" -`; - exports[`Run config declaration-generator-oxc > file content esm/index.d.ts 1`] = ` "export declare const foo = 1; " @@ -137,13 +115,7 @@ exports[`Run config default > cjs structure 1`] = `null`; exports[`Run config default > dist structure 1`] = `null`; -exports[`Run config default > es2017 structure 1`] = ` -[ - "es2017/", - "├── index.d.ts", - "└── index.js", -] -`; +exports[`Run config default > es2017 structure 1`] = `null`; exports[`Run config default > esm structure 1`] = ` [ @@ -157,12 +129,7 @@ exports[`Run config no-declaration > cjs structure 1`] = `null`; exports[`Run config no-declaration > dist structure 1`] = `null`; -exports[`Run config no-declaration > es2017 structure 1`] = ` -[ - "es2017/", - "└── index.js", -] -`; +exports[`Run config no-declaration > es2017 structure 1`] = `null`; exports[`Run config no-declaration > esm structure 1`] = ` [ @@ -259,14 +226,7 @@ exports[`Run config sourcemap-enable > cjs structure 1`] = `null`; exports[`Run config sourcemap-enable > dist structure 1`] = `null`; -exports[`Run config sourcemap-enable > es2017 structure 1`] = ` -[ - "es2017/", - "├── index.d.ts", - "├── index.js", - "└── index.js.map", -] -`; +exports[`Run config sourcemap-enable > es2017 structure 1`] = `null`; exports[`Run config sourcemap-enable > esm structure 1`] = ` [ diff --git a/tests/integration/default/index.test.ts b/tests/integration/default/index.test.ts index 6a4268ad..da31fe60 100644 --- a/tests/integration/default/index.test.ts +++ b/tests/integration/default/index.test.ts @@ -10,15 +10,13 @@ runProjectTest(import.meta.url, [ name: 'bundle', snapshot: 'structure', config: { - transform: { formats: [] }, - bundle: {}, + pkgs: ['!esm'], }, }, { name: 'bundle-full', snapshot: 'structure', config: { - transform: { formats: [] }, bundle: { formats: ['cjs', 'es2017', 'esm', 'umd'], }, @@ -28,7 +26,7 @@ runProjectTest(import.meta.url, [ name: 'bundle-with-full-modes', snapshot: 'structure', config: { - transform: { formats: [] }, + pkgs: [{ module: 'esm', target: 'es5', bundle: true }], bundle: { modes: ['development', 'production'], }, @@ -38,7 +36,7 @@ runProjectTest(import.meta.url, [ name: 'bundle-with-dev-mode', snapshot: 'structure', config: { - transform: { formats: [] }, + pkgs: [{ module: 'esm', target: 'es5', bundle: true }], bundle: { modes: ['development'], }, @@ -48,7 +46,7 @@ runProjectTest(import.meta.url, [ name: 'bundle-with-empty-mode', snapshot: 'structure', config: { - transform: { formats: [] }, + pkgs: [{ module: 'esm', target: 'es5', bundle: true }], bundle: { modes: [], }, diff --git a/tests/integration/syntax-target/__snapshots__/index.test.ts.snap b/tests/integration/syntax-target/__snapshots__/index.test.ts.snap new file mode 100644 index 00000000..a2aa0513 --- /dev/null +++ b/tests/integration/syntax-target/__snapshots__/index.test.ts.snap @@ -0,0 +1,231 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Run config rolldown > dist structure 1`] = ` +[ + "dist/", + "├── es2017/", + "│ └── index.esm.es2017.production.js", + "├── es2022/", + "│ └── index.esm.es2022.production.js", + "└── es5/", + " ├── index.esm.es5.production.js", + " └── vendor.esm.es5.production.js", +] +`; + +exports[`Run config rolldown > file content dist/es5/index.esm.es5.production.js 1`] = `"import{a as e,c as t,i as n,l as r,n as i,o as a,r as o,s,t as c}from"./vendor.esm.es5.production.js";var l=new WeakMap,u=function(){function o(){t(this,o),a(this,l,{writable:!0,value:0})}return i(o,[{key:\`increment\`,value:function(){return e(this,l,s(this,l)+n(o,o,d)),s(this,l)}},{key:\`fetchValue\`,value:function(){return r(function(){return c(this,function(e){return[2,s(this,l)]})}).call(this)}}]),o}(),d={writable:!0,value:1};o(u,u,d,2);var f=function(e){return e*2};function p(e){return r(function(){var t;return c(this,function(n){switch(n.label){case 0:return[4,Promise.resolve(e)];case 1:return t=n.sent(),[2,f(t)]}})})()}export{u as Counter,f as double,p as fetchDouble};"`; + +exports[`Run config rolldown > file content dist/es5/vendor.esm.es5.production.js 1`] = `"function e(e,t,n,r,i,a,o){try{var s=e[a](o),c=s.value}catch(e){n(e);return}s.done?t(c):Promise.resolve(c).then(r,i)}function t(t){return function(){var n=this,r=arguments;return new Promise(function(i,a){var o=t.apply(n,r);function s(t){e(o,i,a,s,c,\`next\`,t)}function c(t){e(o,i,a,s,c,\`throw\`,t)}s(void 0)})}}function n(e,t){if(!(e instanceof t))throw TypeError(\`Cannot call a class as a function\`)}function r(e,t){return t.get?t.get.call(e):t.value}function i(e,t,n){if(!t.has(e))throw TypeError(\`attempted to \`+n+\` private field on non-instance\`);return t.get(e)}function a(e,t){return r(e,i(e,t,\`get\`))}function o(e,t){if(t.has(e))throw TypeError(\`Cannot initialize the same private elements twice on an object\`)}function s(e,t,n){o(e,t),t.set(e,n)}function c(e,t,n){if(t.set)t.set.call(e,n);else{if(!t.writable)throw TypeError(\`attempted to set read only private field\`);t.value=n}}function l(e,t,n){return c(e,i(e,t,\`set\`),n),n}function u(e,t){if(e!==t)throw TypeError(\`Private static access of wrong provenance\`)}function d(e,t){if(e===void 0)throw TypeError(\`attempted to \`+t+\` private static field before its declaration\`)}function f(e,t,n){return u(e,t),d(n,\`get\`),r(e,n)}function p(e,t,n,r){return u(e,t),d(n,\`set\`),c(e,n,r),r}function m(e,t){for(var n=0;n0&&a[a.length-1]))&&(s[0]===6||s[0]===2)){n=0;continue}if(s[0]===3&&(!a||s[1]>a[0]&&s[1] file content dist/es2017/index.esm.es2017.production.js 1`] = `"function e(e,t){if(t.has(e))throw TypeError(\`Cannot initialize the same private elements twice on an object\`)}function t(t,n,r){e(t,n),n.set(t,r)}function n(e,t,n){if(typeof e==\`function\`?e===t:e.has(t))return arguments.length<3?t:n;throw TypeError(\`Private element is not present on this object\`)}function r(e,t){return e.get(n(e,t))}function i(e,t,r){return e.set(n(e,t),r),r}var a=new WeakMap,o=class{constructor(){t(this,a,0)}increment(){return i(a,this,r(a,this)+s._),r(a,this)}async fetchValue(){return r(a,this)}},s={_:1};s._=2;const c=e=>e*2;async function l(e){return c(await Promise.resolve(e))}export{o as Counter,c as double,l as fetchDouble};"`; + +exports[`Run config rolldown > file content dist/es2022/index.esm.es2022.production.js 1`] = `"var e=class e{#e=0;static#t=1;static{e.#t=2}increment(){return this.#e+=e.#t,this.#e}async fetchValue(){return this.#e}};const t=e=>e*2;async function n(e){return t(await Promise.resolve(e))}export{e as Counter,t as double,n as fetchDouble};"`; + +exports[`Run config rollup > dist structure 1`] = ` +[ + "dist/", + "├── es2017/", + "│ ├── index.esm.es2017.production.js", + "│ └── vendor.esm.es2017.production.js", + "├── es2022/", + "│ └── index.esm.es2022.production.js", + "└── es5/", + " ├── index.esm.es5.production.js", + " └── vendor.esm.es5.production.js", +] +`; + +exports[`Run config rollup > es2017 structure 1`] = ` +[ + "es2017/", + "└── index.js", +] +`; + +exports[`Run config rollup > es2022 structure 1`] = ` +[ + "es2022/", + "└── index.js", +] +`; + +exports[`Run config rollup > esm structure 1`] = ` +[ + "esm/", + "└── index.js", +] +`; + +exports[`Run config rollup > file content dist/es5/index.esm.es5.production.js 1`] = ` +"import{_ as e,a as t,b as n,c as r,d as u,e as s,f as i,g as a,h as o}from"./vendor.esm.es5.production.js";var c=new WeakMap,f=function(){function e(){r(this,e),u(this,c,{writable:!0,value:0})}return t(e,[{key:"increment",value:function(){return s(this,c,i(this,c)+a(e,e,l)),i(this,c)}},{key:"fetchValue",value:function(){return n(function(){return o(this,function(e){return[2,i(this,c)]})}).call(this)}}]),e}(),l={writable:!0,value:1};e(f,f,l,2);var h=function(e){return 2*e};function v(e){return n(function(){return o(this,function(t){switch(t.label){case 0:return[4,Promise.resolve(e)];case 1:return[2,h(t.sent())]}})})()}export{f as Counter,h as double,v as fetchDouble}; +" +`; + +exports[`Run config rollup > file content dist/es5/vendor.esm.es5.production.js 1`] = ` +"function e(e,t,r,n,a,o,i){try{var c=e[o](i),s=c.value}catch(e){r(e);return}c.done?t(s):Promise.resolve(s).then(n,a)}function t(t){return function(){var r=this,n=arguments;return new Promise(function(a,o){var i=t.apply(r,n);function c(t){e(i,a,o,c,s,"next",t)}function s(t){e(i,a,o,c,s,"throw",t)}c(void 0)})}}function r(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function n(e,t){return t.get?t.get.call(e):t.value}function a(e,t,r){if(!t.has(e))throw TypeError("attempted to "+r+" private field on non-instance");return t.get(e)}function o(e,t){var r=a(e,t,"get");return n(e,r)}function i(e,t,r){if(t.has(e))throw TypeError("Cannot initialize the same private elements twice on an object");t.set(e,r)}function c(e,t,r){if(t.set)t.set.call(e,r);else{if(!t.writable)throw TypeError("attempted to set read only private field");t.value=r}}function s(e,t,r){var n=a(e,t,"set");return c(e,n,r),r}function l(e,t){if(e!==t)throw TypeError("Private static access of wrong provenance")}function u(e,t){if(void 0===e)throw TypeError("attempted to "+t+" private static field before its declaration")}function f(e,t,r){return l(e,t),u(r,"get"),n(e,r)}function p(e,t,r,n){return l(e,t),u(r,"set"),c(e,r,n),n}function _(e,t,r){return t&&function(e,t){for(var r=0;r0&&a[a.length-1])&&(6===l[0]||2===l[0])){o=0;continue}if(3===l[0]&&(!a||l[1]>a[0]&&l[1] file content dist/es2017/index.esm.es2017.production.js 1`] = ` +"import{_ as e,a as t,b as r,c as a,d as s}from"./vendor.esm.es2017.production.js";var n=new WeakMap;class o{increment(){return t(this,n,r(this,n)+a(o,o,i)),r(this,n)}async fetchValue(){return r(this,n)}constructor(){s(this,n,{writable:!0,value:0})}}var i={writable:!0,value:1};e(o,o,i,2);let u=e=>2*e;async function c(e){return u(await Promise.resolve(e))}export{o as Counter,u as double,c as fetchDouble}; +" +`; + +exports[`Run config rollup > file content dist/es2017/vendor.esm.es2017.production.js 1`] = ` +"function t(t,e){return e.get?e.get.call(t):e.value}function e(t,e,r){if(!e.has(t))throw TypeError("attempted to "+r+" private field on non-instance");return e.get(t)}function r(r,i){var a=e(r,i,"get");return t(r,a)}function i(t,e,r){if(e.has(t))throw TypeError("Cannot initialize the same private elements twice on an object");e.set(t,r)}function a(t,e,r){if(e.set)e.set.call(t,r);else{if(!e.writable)throw TypeError("attempted to set read only private field");e.value=r}}function n(t,r,i){var n=e(t,r,"set");return a(t,n,i),i}function s(t,e){if(t!==e)throw TypeError("Private static access of wrong provenance")}function o(t,e){if(void 0===t)throw TypeError("attempted to "+e+" private static field before its declaration")}function c(e,r,i){return s(e,r),o(i,"get"),t(e,i)}function f(t,e,r,i){return s(t,e),o(r,"set"),a(t,r,i),i}export{f as _,n as a,r as b,c as c,i as d}; +" +`; + +exports[`Run config rollup > file content dist/es2022/index.esm.es2022.production.js 1`] = ` +"class t{#t=0;static #e=1;static{t.#e=2}increment(){return this.#t+=t.#e,this.#t}async fetchValue(){return this.#t}}let e=t=>2*t;async function u(t){return e(await Promise.resolve(t))}export{t as Counter,e as double,u as fetchDouble}; +" +`; + +exports[`Run config rollup > file content es2017/index.js 1`] = ` +"import { _ as _$2 } from '@swc/helpers/_/_class_private_field_get'; +import { _ as _$4 } from '@swc/helpers/_/_class_private_field_init'; +import { _ as _$1 } from '@swc/helpers/_/_class_private_field_set'; +import { _ as _$3 } from '@swc/helpers/_/_class_static_private_field_spec_get'; +import { _ } from '@swc/helpers/_/_class_static_private_field_spec_set'; + +var _count = /*#__PURE__*/ new WeakMap(); +// ES2015: class, arrow function +// ES2017: async/await +// ES2022: class private fields, static class blocks +class Counter { + increment() { + _$1(this, _count, _$2(this, _count) + _$3(Counter, Counter, _defaultStep)); + return _$2(this, _count); + } + async fetchValue() { + return _$2(this, _count); + } + constructor(){ + _$4(this, _count, { + writable: true, + value: 0 + }); + } +} +var _defaultStep = { + writable: true, + value: 1 +}; +_(Counter, Counter, _defaultStep, 2); +const double = (n)=>n * 2; +async function fetchDouble(n) { + const result = await Promise.resolve(n); + return double(result); +} + +export { Counter, double, fetchDouble }; +" +`; + +exports[`Run config rollup > file content es2022/index.js 1`] = ` +"// ES2015: class, arrow function +// ES2017: async/await +// ES2022: class private fields, static class blocks +class Counter { + #count = 0; + static #defaultStep = 1; + static{ + Counter.#defaultStep = 2; + } + increment() { + this.#count += Counter.#defaultStep; + return this.#count; + } + async fetchValue() { + return this.#count; + } +} +const double = (n)=>n * 2; +async function fetchDouble(n) { + const result = await Promise.resolve(n); + return double(result); +} + +export { Counter, double, fetchDouble }; +" +`; + +exports[`Run config rollup > file content esm/index.js 1`] = ` +"import { _ as _$5 } from '@swc/helpers/_/_async_to_generator'; +import { _ as _$7 } from '@swc/helpers/_/_class_call_check'; +import { _ as _$3 } from '@swc/helpers/_/_class_private_field_get'; +import { _ as _$8 } from '@swc/helpers/_/_class_private_field_init'; +import { _ as _$2 } from '@swc/helpers/_/_class_private_field_set'; +import { _ as _$4 } from '@swc/helpers/_/_class_static_private_field_spec_get'; +import { _ } from '@swc/helpers/_/_class_static_private_field_spec_set'; +import { _ as _$1 } from '@swc/helpers/_/_create_class'; +import { _ as _$6 } from '@swc/helpers/_/_ts_generator'; + +var _count = /*#__PURE__*/ new WeakMap(); +// ES2015: class, arrow function +// ES2017: async/await +// ES2022: class private fields, static class blocks +var Counter = /*#__PURE__*/ function() { + function Counter() { + _$7(this, Counter); + _$8(this, _count, { + writable: true, + value: 0 + }); + } + _$1(Counter, [ + { + key: "increment", + value: function increment() { + _$2(this, _count, _$3(this, _count) + _$4(Counter, Counter, _defaultStep)); + return _$3(this, _count); + } + }, + { + key: "fetchValue", + value: function fetchValue() { + return _$5(function() { + return _$6(this, function(_state) { + return [ + 2, + _$3(this, _count) + ]; + }); + }).call(this); + } + } + ]); + return Counter; +}(); +var _defaultStep = { + writable: true, + value: 1 +}; +_(Counter, Counter, _defaultStep, 2); +var double = function(n) { + return n * 2; +}; +function fetchDouble(n) { + return _$5(function() { + var result; + return _$6(this, function(_state) { + switch(_state.label){ + case 0: + return [ + 4, + Promise.resolve(n) + ]; + case 1: + result = _state.sent(); + return [ + 2, + double(result) + ]; + } + }); + })(); +} + +export { Counter, double, fetchDouble }; +" +`; diff --git a/tests/integration/syntax-target/index.test.ts b/tests/integration/syntax-target/index.test.ts new file mode 100644 index 00000000..02b90e4f --- /dev/null +++ b/tests/integration/syntax-target/index.test.ts @@ -0,0 +1,37 @@ +import { runProjectTest } from '../../helpers/run'; + +runProjectTest(import.meta.url, [ + { + name: 'rollup', + config: { + declaration: false, + sourceMaps: false, + pkgs: [ + // Transform 三种语法目标 + { module: 'esm', target: 'es5', outputDir: 'esm' }, + 'es2017', + 'es2022', + // Bundle 三种语法目标 + { module: 'esm', target: 'es5', bundle: true, outputDir: 'dist/es5' }, + { module: 'esm', target: 'es2017', bundle: true, outputDir: 'dist/es2017' }, + { module: 'esm', target: 'es2022', bundle: true, outputDir: 'dist/es2022' }, + ], + }, + snapshot: 'full', + snapshotFolders: ['esm', 'es2017', 'es2022', 'dist'], + }, + { + name: 'rolldown', + config: { + declaration: false, + sourceMaps: false, + pkgs: [ + { module: 'esm', target: 'es5', bundle: true, outputDir: 'dist/es5', engine: 'rolldown' }, + { module: 'esm', target: 'es2017', bundle: true, outputDir: 'dist/es2017', engine: 'rolldown' }, + { module: 'esm', target: 'es2022', bundle: true, outputDir: 'dist/es2022', engine: 'rolldown' }, + ], + }, + snapshot: 'full', + snapshotFolders: ['dist'], + }, +]); diff --git a/tests/integration/syntax-target/package.json b/tests/integration/syntax-target/package.json new file mode 100644 index 00000000..b20dea92 --- /dev/null +++ b/tests/integration/syntax-target/package.json @@ -0,0 +1,10 @@ +{ + "name": "@ice/pkg-tests-syntax-target", + "version": "0.0.0", + "description": "Integration tests for syntax compilation targets (es5/es2017/es2022) in both transform and bundle modes", + "private": true, + "dependencies": { + "@ice/pkg": "workspace:*", + "@swc/helpers": "^0.5.15" + } +} diff --git a/tests/integration/syntax-target/src/index.ts b/tests/integration/syntax-target/src/index.ts new file mode 100644 index 00000000..9314c5a7 --- /dev/null +++ b/tests/integration/syntax-target/src/index.ts @@ -0,0 +1,28 @@ +// ES2015: class, arrow function +// ES2017: async/await +// ES2022: class private fields, static class blocks +export class Counter { + #count = 0; + + static #defaultStep = 1; + + static { + Counter.#defaultStep = 2; + } + + increment(): number { + this.#count += Counter.#defaultStep; + return this.#count; + } + + async fetchValue(): Promise { + return this.#count; + } +} + +export const double = (n: number) => n * 2; + +export async function fetchDouble(n: number): Promise { + const result = await Promise.resolve(n); + return double(result); +} diff --git a/website/docs/config/bundle.md b/website/docs/config/bundle.md index 90811f46..52494469 100644 --- a/website/docs/config/bundle.md +++ b/website/docs/config/bundle.md @@ -8,15 +8,10 @@ 推荐使用 [`pkgs`](./pkgs) 替代 `formats` 来配置多产物输出,`pkgs` 提供更灵活的差异化配置能力。 ::: -- 类型:`['esm', 'umd', 'cjs', 'es2017']` -- 默认值:`['esm', 'es2017']` +- 类型:`['esm', 'umd', 'cjs', 'es2017', 'es2022', 'mf']` +- 默认值:无 -输出的类型,默认是输出 `esm` 和 `es2017` 产物。 - -```shell title=root/dist -- index.esm.es5.production.js # 输出 ES module + es5 产物 -- index.esm.es2017.production.js # 输出 ES module + es2017 产物 -``` +输出的 Bundle 格式类型。未配置时不产生任何 Bundle 产物,需显式指定至少一种格式: 若只需要产出 umd 规范产物,可配置为: diff --git a/website/docs/config/pkgs.md b/website/docs/config/pkgs.md index acf93d57..ffe6724c 100644 --- a/website/docs/config/pkgs.md +++ b/website/docs/config/pkgs.md @@ -3,7 +3,7 @@ `@ice/pkg` 2.0 引用的新式配置方式 - 类型:`Array` -- 默认值:`undefined` +- 默认值:`['esm']`(当 `pkgs`、`transform.formats`、`bundle.formats` 均未配置时) 配置多个构建单元(package),每个 pkg 可以独立控制构建模式、格式、入口、输出目录等。适用于需要同时输出多种格式或多个子包的场景。 @@ -21,8 +21,8 @@ export default defineConfig({ 支持的预设值: -- Transform 格式(直接字符串):`'esm'`、`'cjs'`、`'es2017'` -- Bundle 格式(以 `!` 为前缀):`'!esm'`、`'!cjs'`、`'!es2017'`、`'!umd'`、`'!mf'` +- Transform 格式(直接字符串):`'esm'`、`'cjs'`、`'es2017'`、`'es2022'` +- Bundle 格式(以 `!` 为前缀):`'!esm'`、`'!cjs'`、`'!es2017'`、`'!es2022'`、`'!umd'`、`'!mf'` ## PkgUserConfig 配置项 @@ -103,6 +103,22 @@ export default defineConfig({ 禁用该 pkg,构建时跳过。可以在不改动配置的情况下,通过环境变量或者其他变量进行控制。 +## 条件配置 + +`pkgs` 数组中的 `false`、`undefined` 等假值会被自动忽略,因此可以使用 `condition && { ... }` 语法来按条件包含某个 pkg,无需额外的 if 判断: + +```ts title="build.config.mts" +import { defineConfig } from '@ice/pkg'; + +const enableCJS = process.env.ENABLE_CJS === 'true'; + +export default defineConfig({ + pkgs: ['esm', enableCJS && { module: 'cjs', target: 'es2017' }], +}); +``` + +当 `enableCJS` 为 `false` 时,`false && { ... }` 的结果 `false` 会被忽略,等同于只配置了 `'esm'`。 + --- 以下配置项含义与对应的顶层或 bundle 配置相同,在 pkg 中配置时会按优先级覆盖全局配置,仅作用于当前 pkg: diff --git a/website/docs/config/transform.md b/website/docs/config/transform.md index cf50ca03..0577031a 100644 --- a/website/docs/config/transform.md +++ b/website/docs/config/transform.md @@ -1,20 +1,10 @@ # transform :::tip -Transform 模式是 ICE PKG 默认的编译模式。 +Transform 模式是 ICE PKG 默认的编译模式。推荐使用 [`pkgs`](./pkgs) 配置多产物输出。 ::: -该字段定义 [Transform 模式](../guide/build-modes#transform-模式) 下额外的配置。默认配置是: - -```ts title="build.config.mts" -import { defineConfig } from '@ice/pkg'; - -export default defineConfig({ - transform: { - formats: ['esm', 'es2017'], - }, -}); -``` +该字段定义 [Transform 模式](../guide/build-modes#transform-模式) 下额外的配置。 ## formats @@ -22,17 +12,10 @@ export default defineConfig({ 推荐使用 [`pkgs`](./pkgs) 替代 `formats` 来配置多产物输出,`pkgs` 提供更灵活的差异化配置能力。 ::: -- 类型:`Array<'cjs' | 'esm' | 'es2017'>` -- 默认值:`['esm', 'es2017']` - -输出的类型。ICE PKG 会默认把产物输出到 `esm` (输出 ES module + ES5 产物) 和 `es2017` (输出 ES module + ES2017 产物) 两个文件夹。 - -```shell -- esm # ES module + ES5 产物 -- es2017 # ES module + ES2017 产物 -``` +- 类型:`Array<'cjs' | 'esm' | 'es2017' | 'es2022'>` +- 默认值:无 -若想要输出 CommonJS 产物,可如下配置: +输出的格式类型。若想同时输出多种格式,可如下配置: ```ts title="build.config.mts" import { defineConfig } from '@ice/pkg'; diff --git a/website/docs/guide/build.md b/website/docs/guide/build.md index 03fa9505..e5fe7023 100644 --- a/website/docs/guide/build.md +++ b/website/docs/guide/build.md @@ -4,24 +4,26 @@ ## 构建产物说明 -ICE PKG 默认支持 `esm`、`es2017`、`cjs`、`umd`、`mf` 五种构建产物类型。每种产物类型在不同构建模式下支持情况、模块规范、语法规范说明如下表: +ICE PKG 默认支持 `esm`、`es2017`、`es2022`、`cjs`、`umd`、`mf` 六种构建产物类型。每种产物类型在不同构建模式下支持情况、模块规范、语法规范说明如下表: | 产物类型 | Transform 模式 | Bundle 模式 | 模块规范 | 语法规范 | | :------: | :------------: | :---------: | :---------------: | :------: | | `esm` | ✅支持 | ✅支持 | ES Module | ES5 | | `es2017` | ✅支持 | ✅支持 | ES Module | ES2017 | +| `es2022` | ✅支持 | ✅支持 | ES Module | ES2022 | | `cjs` | ✅支持 | ✅支持 | CommonJS | ES5 | | `umd` | ❌不支持 | ✅支持 | UMD | ES5 | | `mf` | ❌不支持 | ✅支持 | Module Federation | — | 每种构建产物的优缺点和适用场景如下表所示: -| 产物类型 | 优点 | 缺点 | 适用场景 | -| :------: | ---------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------ | -| `esm` | 兼容性较好 | 体积大 | 消费产物的应用打包时不编译 `node_modules`;或者运行环境支持的 ECMAScript 版本较低 | -| `es2017` | 保留大部分 JavaScript 语法,体积小 | 兼容性差 | 消费产物的应用打包时编译 `node_modules`;或者运行环境支持的 ES2017 语法。更多说明可参考[文档](./build#es2017-产物) | -| `cjs` | 兼容各版本的 Node.js | 体积大 | 在 Node.js 环境下运行 | -| `umd` | 兼容运行在浏览器和 Node.js 中 | 体积大 | 用户的项目中某个依赖 external,需要在 HTML 中通过 `