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
5 changes: 5 additions & 0 deletions .changeset/mean-rice-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ice/pkg': major
---

feat: change default formats to 'esm'
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -45,6 +47,7 @@ packages/*/es/
examples/**/esm
examples/**/es
examples/**/es2017
examples/**/es2022
examples/**/cjs
examples/**/lib
examples/**/dist
Expand Down
71 changes: 56 additions & 15 deletions packages/pkg/src/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
});

Expand Down
9 changes: 3 additions & 6 deletions packages/pkg/src/config/userConfig.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import type { TransformUserConfig } from '../types.js';

function getUserConfig() {
const defaultTransformUserConfig: TransformUserConfig = {
formats: ['esm', 'es2017'],
};
const userConfig = [
{
name: 'entry',
Expand All @@ -30,11 +25,13 @@ function getUserConfig() {
},
{
name: 'transform',
defaultValue: defaultTransformUserConfig,
},
{
name: 'bundle',
},
{
name: 'pkgs',
},
Comment thread
XGHeaven marked this conversation as resolved.
];
return userConfig;
}
Expand Down
6 changes: 5 additions & 1 deletion packages/pkg/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ export const JSX_RUNTIME_SOURCE = '@ice/jsx-runtime';
export const ALIAS_TRANSFORM_FORMATS_MAP: Record<AliasTransformFormatString, StandardTransformFormatString> = {
esm: 'esm:es5',
es2017: 'esm:es2017',
es2022: 'esm:es2022',
cjs: 'cjs:es5',
};

export const ALIAS_BUNDLE_FORMATS_MAP: Record<AliasBundleFormatString, StandardBundleFormatString> = {
export const ALIAS_BUNDLE_FORMATS_MAP: Record<
Exclude<AliasBundleFormatString, 'es2022'>,
StandardBundleFormatString
> = {
umd: 'umd:es5',
esm: 'esm:es5',
es2017: 'esm:es2017',
Expand Down
15 changes: 8 additions & 7 deletions packages/pkg/src/core/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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.',
Comment thread
XGHeaven marked this conversation as resolved.
);
}

await runPkgPlugins(ctx, pkgs);
Comment thread
XGHeaven marked this conversation as resolved.
registerPkgTasks(ctx, pkgs);

initContextTasks(ctx);

await ctx['runCliOption']();
Expand Down
4 changes: 3 additions & 1 deletion packages/pkg/src/core/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<Exclude<AliasBundleFormatString, 'es2017'>> | undefined;
const es5Formats = aliasedFormatsGroup.es5 as
| Array<Exclude<AliasBundleFormatString, 'es2017' | 'es2022'>>
| undefined;
config.formats = [...(es5Formats?.map((module) => createFormat(module, 'es5')) ?? [])];
} else {
// 理论上 Pkg 模式不会出现这个情况,但为了健壮性还是尝试补上这部分
Expand Down
37 changes: 33 additions & 4 deletions packages/pkg/src/core/pkg.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
AliasBundleFormatString,
Context,
PresetPkg,
PkgResolvedConfig,
PkgUserConfig,
PluginInfo,
Expand Down Expand Up @@ -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(
Expand All @@ -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
Expand Down Expand Up @@ -144,8 +158,21 @@ function resolveExtends(extendsConfig: string[] = [], pkgsMap: Map<string, PkgRe

export async function resolvePackage(ctx: Context) {
const { userConfig } = ctx;
// filter undefined or boolean out
const pkgs = userConfig.pkgs ?? [];

// Derive pkgs from transform.formats / bundle.formats if not explicitly set,
// falling back to the default ['esm'] when nothing is configured at all.
const transformPresets = (userConfig.transform?.formats ?? []) as string[];
const bundlePresets = (userConfig.bundle?.formats ?? []).map((f) => `!${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<string>(rawPkgs.filter((p): p is PresetPkg => typeof p === 'string'));
const pkgs = [...rawPkgs, ...(legacyPresets.filter((p) => !existingStrings.has(p)) as PresetPkg[])];
Comment thread
XGHeaven marked this conversation as resolved.
const resolvedPkgs: PkgResolvedConfig[] = [];
const pkgsMap = new Map<string, PkgResolvedConfig>();

Expand Down Expand Up @@ -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<Exclude<AliasBundleFormatString, 'es2017'>> | undefined;
const es5Formats = aliasedFormatsGroup.es5 as
| Array<Exclude<AliasBundleFormatString, 'es2017' | 'es2022'>>
| undefined;

if (es5Formats?.length) {
const resolvedPkg: PkgResolvedConfig = {
Expand Down
100 changes: 1 addition & 99 deletions packages/pkg/src/core/register.ts
Original file line number Diff line number Diff line change
@@ -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']) {
Expand All @@ -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<TransformFormat>(ALIAS_TRANSFORM_FORMATS_MAP[format]);
registerBuiltinTask(`transform-${format}`, {
type: 'transform',
format: fmt,
});
} else {
const structFormat = tryToFormat<TransformFormat>(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<Exclude<AliasBundleFormatString, 'es2017'>> | 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<BundleFormat>(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);
Expand Down
10 changes: 5 additions & 5 deletions packages/pkg/src/engine/shared/swcConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ const BROWSER_TARGETS_MAP: Record<JsTarget, any> = {
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',
},
};

Expand Down
Loading
Loading