Skip to content

Commit b2a8a11

Browse files
committed
feat: support pkg options
issue: #682
1 parent 1210fb9 commit b2a8a11

File tree

22 files changed

+950
-173
lines changed

22 files changed

+950
-173
lines changed

.changeset/slimy-walls-tease.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@ice/pkg': minor
3+
---
4+
5+
feat: support `pkg` options

packages/pkg/src/cli.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import consola from 'consola';
33
import { cac } from 'cac';
44
import { readFileSync } from 'node:fs';
55
import { join, dirname } from 'node:path';
6-
import { createPkg } from './core/createPkg.js';
6+
import { createCore } from './core/create.js';
77

88
const __dirname = dirname(fileURLToPath(import.meta.url));
99

@@ -25,7 +25,7 @@ const cli = cac('ice-pkg');
2525
delete options['--'];
2626
const { rootDir, ...commandArgs } = options;
2727

28-
const pkg = await createPkg({
28+
const pkg = await createCore({
2929
rootDir: options.rootDir,
3030
command: 'build',
3131
commandArgs,
@@ -49,7 +49,7 @@ const cli = cac('ice-pkg');
4949
delete options['--'];
5050
const { rootDir, ...commandArgs } = options;
5151

52-
const pkg = await createPkg({
52+
const pkg = await createCore({
5353
rootDir: options.rootDir,
5454
command: 'start',
5555
commandArgs,

packages/pkg/src/core/createPkg.ts renamed to packages/pkg/src/core/create.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ import { Context, CustomFormatTaskCreator, ExtendsPluginAPI, TaskConfig, UserCon
44
import taskRegisterPlugin from '../plugins/component.js';
55
import { userConfigSchema } from '../config/schema.js';
66
import { createMessageBuilder, fromZodError } from 'zod-validation-error';
7-
import { registerTasks } from './registerTasks.js';
8-
import { initContextTasks } from './initContextTasks.js';
7+
import { registerPkgTasks, registerTasks } from './register.js';
8+
import { initContextTasks } from './init.js';
9+
import { resolvePackage, runPkgPlugins } from './pkg.js';
910

1011
export interface CreatePkgOptions {
1112
rootDir: string;
@@ -37,7 +38,7 @@ export interface PkgCore {
3738
*
3839
* 为了实现以上流程,需要魔改 build-scripts 的部分逻辑,所以会尝试调用其 private 方法
3940
*/
40-
export async function createPkg(options: CreatePkgOptions) {
41+
export async function createCore(options: CreatePkgOptions) {
4142
const customFormats: Record<string, CustomFormatTaskCreator> = {};
4243

4344
const extendsPluginAPI: ExtendsPluginAPI = {
@@ -105,7 +106,15 @@ export async function createPkg(options: CreatePkgOptions) {
105106
throw prettyError;
106107
}
107108

108-
registerTasks(ctx, customFormats);
109+
const pkgs = await resolvePackage(ctx);
110+
await runPkgPlugins(ctx, pkgs);
111+
112+
if (pkgs.length) {
113+
// when pkg is preset, no need to register old tasks
114+
await registerPkgTasks(ctx, pkgs);
115+
} else {
116+
registerTasks(ctx, customFormats);
117+
}
109118

110119
initContextTasks(ctx);
111120

packages/pkg/src/core/init.ts

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import { BuildTask, BundleUserConfig, Context, DeclarationUserConfig } from '../types.js';
2+
import { formatEntry, getTransformDefaultOutputDir } from '../helpers/getTaskIO.js';
3+
import getDefaultDefineValues from '../helpers/getDefaultDefineValues.js';
4+
import { stringifyObject } from '../utils.js';
5+
import { merge, mergeWith, omit } from 'es-toolkit/object';
6+
import path from 'node:path';
7+
import { groupBy } from 'es-toolkit';
8+
9+
const mergeDefaults: typeof merge = (target, source) => {
10+
return mergeWith(target, source, (targetValue, sourceValue) => {
11+
return targetValue ?? sourceValue;
12+
});
13+
};
14+
15+
const defaultMinifyFunction = (mode: string, command: string) => {
16+
return mode === 'production' && command === 'build';
17+
};
18+
19+
const defaultBundleUserConfig: BundleUserConfig = {
20+
outputDir: 'dist',
21+
minify: {
22+
js: defaultMinifyFunction,
23+
css: defaultMinifyFunction,
24+
},
25+
polyfill: 'usage',
26+
compileDependencies: false,
27+
};
28+
29+
const defaultDeclarationUserConfig = {
30+
outputMode: 'multi',
31+
} satisfies DeclarationUserConfig;
32+
33+
export function initContextTasks(ctx: Context) {
34+
const tasks = ctx.getTaskConfig() as BuildTask[];
35+
36+
const { declaration: declarationTasks, buildable: buildableTasks } = groupBy(tasks, (task) =>
37+
task.config.type === 'declaration' ? 'declaration' : 'buildable',
38+
);
39+
40+
// 1. init all tasks except declaration
41+
for (const buildTask of buildableTasks) {
42+
initTask(buildTask, ctx);
43+
}
44+
45+
// 2. init declaration based on transform tasks
46+
for (const buildTask of declarationTasks ?? []) {
47+
initDeclarationTask(buildTask, ctx, buildableTasks);
48+
}
49+
}
50+
51+
type InitTaskOptions = Pick<Context, 'userConfig' | 'rootDir' | 'command'>;
52+
53+
function initSharedTask(buildTask: BuildTask, options: InitTaskOptions) {
54+
const { userConfig, command } = options;
55+
const { config } = buildTask;
56+
const { pkg } = config;
57+
58+
config.entry = formatEntry(config.entry ?? pkg?.entry ?? userConfig.entry);
59+
config.alias ??= mergeDefaults({ ...pkg?.alias }, userConfig.alias ?? {});
60+
// Configure define
61+
config.define = Object.assign(
62+
// Note: The define values in bundle mode will be defined (according to the `modes` value)
63+
// in generating rollup options. But when the command is test, we don't need to get the rollup options.
64+
// So in test, we assume the mode is 'development'.
65+
command === 'test' ? getDefaultDefineValues('development') : {},
66+
stringifyObject(userConfig.define ?? {}),
67+
stringifyObject(pkg?.define ?? {}),
68+
stringifyObject(config.define ?? {}),
69+
);
70+
71+
config.sourcemap ??= pkg?.sourceMaps ?? userConfig.sourceMaps ?? command === 'start';
72+
config.jsxRuntime ??= pkg?.jsxRuntime ?? userConfig.jsxRuntime;
73+
}
74+
75+
/**
76+
* @internal export for test
77+
*/
78+
export function initTask(buildTask: BuildTask, options: InitTaskOptions) {
79+
const { userConfig, rootDir, command } = options;
80+
const { config, name: taskName } = buildTask;
81+
const { pkg } = config;
82+
83+
initSharedTask(buildTask, options);
84+
85+
const expectedMode = command === 'build' ? 'production' : 'development';
86+
87+
if (config.type === 'bundle') {
88+
const bundleConfig = userConfig.bundle ?? {};
89+
config.modes ??= bundleConfig.modes ?? [expectedMode];
90+
// TODO: 判断下这个东西是否真的有用
91+
// Set outputDir to process.env for CI
92+
process.env.ICE_PKG_BUNDLE_OUTPUT_DIR = config.outputDir;
93+
const originMinifyConfig = pkg?.minify ?? bundleConfig.minify ?? defaultBundleUserConfig.minify ?? {};
94+
let { jsMinify, cssMinify } = config;
95+
if (typeof originMinifyConfig === 'object') {
96+
jsMinify ??= getMinifyFunction(originMinifyConfig.js);
97+
cssMinify ??= getMinifyFunction(originMinifyConfig.css);
98+
} else {
99+
jsMinify ??= getMinifyFunction(originMinifyConfig);
100+
cssMinify ??= getMinifyFunction(originMinifyConfig);
101+
}
102+
103+
config.jsMinify = jsMinify;
104+
config.cssMinify = cssMinify;
105+
106+
config.outputDir ??= pkg?.outputDir ?? bundleConfig.outputDir ?? defaultBundleUserConfig.outputDir;
107+
108+
if (pkg) {
109+
mergeDefaults(config, omit(pkg, ['id', 'pluginInfos', 'id', 'target', 'module', 'declaration', 'outputDir']));
110+
}
111+
mergeDefaults(config, bundleConfig);
112+
mergeDefaults(config, defaultBundleUserConfig);
113+
} else if (config.type === 'transform') {
114+
config.modes ??= [expectedMode];
115+
config.outputDir ??= pkg?.outputDir ?? getTransformDefaultOutputDir(rootDir, taskName, config);
116+
} else if (config.type === 'declaration') {
117+
// should run in initDeclarationTask
118+
} else {
119+
throw new Error('Invalid task type.');
120+
}
121+
122+
return buildTask;
123+
}
124+
125+
/**
126+
* 需要判断 entry 是否一致,对于不一致的 entry,理论上要生成多个 declaration task
127+
* @internal export for test
128+
*/
129+
export function initDeclarationTask(buildTask: BuildTask, options: InitTaskOptions, allTasks: BuildTask[]) {
130+
const { userConfig, rootDir } = options;
131+
const { config } = buildTask;
132+
const { declaration: declarationConfig } = userConfig;
133+
if (config.type !== 'declaration') {
134+
throw new Error('initDeclarationTask only allow declaration task');
135+
}
136+
if (declarationConfig === false) {
137+
throw new Error('Cannot disable declaration when transform formats is not empty.');
138+
}
139+
initSharedTask(buildTask, options);
140+
config.outputMode ??=
141+
declarationConfig === true
142+
? defaultDeclarationUserConfig.outputMode
143+
: (declarationConfig.outputMode ?? defaultDeclarationUserConfig.outputMode);
144+
const allOutputDirs = allTasks
145+
.map((v) => {
146+
return v.config.type === 'transform' ? v.config.outputDir! : '';
147+
})
148+
.filter(Boolean);
149+
// 这个 output 仅仅用于生成正确的 .d.ts 的 alias,不做实际输出目录
150+
config.outputDir = allOutputDirs[0];
151+
if (config.outputMode === 'unique') {
152+
config.declarationOutputDirs = [path.resolve(rootDir, 'typings')];
153+
} else {
154+
config.declarationOutputDirs = allOutputDirs;
155+
}
156+
157+
return buildTask;
158+
}
159+
160+
function getMinifyFunction(minify: boolean | ((mode: string, command: string) => unknown)) {
161+
switch (typeof minify) {
162+
case 'boolean':
163+
return () => minify;
164+
case 'function':
165+
return minify;
166+
}
167+
return defaultMinifyFunction;
168+
}

packages/pkg/src/core/initContextTasks.ts

Lines changed: 0 additions & 132 deletions
This file was deleted.

0 commit comments

Comments
 (0)