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/slimy-walls-tease.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@ice/pkg': minor
---

feat: support `pkg` options
6 changes: 3 additions & 3 deletions packages/pkg/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import consola from 'consola';
import { cac } from 'cac';
import { readFileSync } from 'node:fs';
import { join, dirname } from 'node:path';
import { createPkg } from './core/createPkg.js';
import { createCore } from './core/create.js';

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

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

const pkg = await createPkg({
const pkg = await createCore({
rootDir: options.rootDir,
command: 'build',
commandArgs,
Expand All @@ -49,7 +49,7 @@ const cli = cac('ice-pkg');
delete options['--'];
const { rootDir, ...commandArgs } = options;

const pkg = await createPkg({
const pkg = await createCore({
rootDir: options.rootDir,
command: 'start',
commandArgs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { Context, CustomFormatTaskCreator, ExtendsPluginAPI, TaskConfig, UserCon
import taskRegisterPlugin from '../plugins/component.js';
import { userConfigSchema } from '../config/schema.js';
import { createMessageBuilder, fromZodError } from 'zod-validation-error';
import { registerTasks } from './registerTasks.js';
import { initContextTasks } from './initContextTasks.js';
import { registerPkgTasks, registerTasks } from './register.js';
import { initContextTasks } from './init.js';
import { resolvePackage, runPkgPlugins } from './pkg.js';

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

const extendsPluginAPI: ExtendsPluginAPI = {
Expand Down Expand Up @@ -105,7 +106,15 @@ export async function createPkg(options: CreatePkgOptions) {
throw prettyError;
}

registerTasks(ctx, customFormats);
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, customFormats);
}

initContextTasks(ctx);

Expand Down
168 changes: 168 additions & 0 deletions packages/pkg/src/core/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import { BuildTask, BundleUserConfig, Context, DeclarationUserConfig } from '../types.js';
import { formatEntry, getTransformDefaultOutputDir } from '../helpers/getTaskIO.js';
import getDefaultDefineValues from '../helpers/getDefaultDefineValues.js';
import { stringifyObject } from '../utils.js';
import { merge, mergeWith, omit } from 'es-toolkit/object';
import path from 'node:path';
import { groupBy } from 'es-toolkit';

const mergeDefaults: typeof merge = (target, source) => {
return mergeWith(target, source, (targetValue, sourceValue) => {
return targetValue ?? sourceValue;
});
};

const defaultMinifyFunction = (mode: string, command: string) => {
return mode === 'production' && command === 'build';
};

const defaultBundleUserConfig: BundleUserConfig = {
outputDir: 'dist',
minify: {
js: defaultMinifyFunction,
css: defaultMinifyFunction,
},
polyfill: 'usage',
compileDependencies: false,
};

const defaultDeclarationUserConfig = {
outputMode: 'multi',
} satisfies DeclarationUserConfig;

export function initContextTasks(ctx: Context) {
const tasks = ctx.getTaskConfig() as BuildTask[];

const { declaration: declarationTasks, buildable: buildableTasks } = groupBy(tasks, (task) =>
task.config.type === 'declaration' ? 'declaration' : 'buildable',
);

// 1. init all tasks except declaration
for (const buildTask of buildableTasks) {
initTask(buildTask, ctx);
}

// 2. init declaration based on transform tasks
for (const buildTask of declarationTasks ?? []) {
initDeclarationTask(buildTask, ctx, buildableTasks);
}
}

type InitTaskOptions = Pick<Context, 'userConfig' | 'rootDir' | 'command'>;

function initSharedTask(buildTask: BuildTask, options: InitTaskOptions) {
const { userConfig, command } = options;
const { config } = buildTask;
const { pkg } = config;

config.entry = formatEntry(config.entry ?? pkg?.entry ?? userConfig.entry);
config.alias ??= mergeDefaults({ ...pkg?.alias }, userConfig.alias ?? {});
// Configure define
config.define = Object.assign(
// Note: The define values in bundle mode will be defined (according to the `modes` value)
// in generating rollup options. But when the command is test, we don't need to get the rollup options.
// So in test, we assume the mode is 'development'.
command === 'test' ? getDefaultDefineValues('development') : {},
stringifyObject(userConfig.define ?? {}),
stringifyObject(pkg?.define ?? {}),
stringifyObject(config.define ?? {}),
);

config.sourcemap ??= pkg?.sourceMaps ?? userConfig.sourceMaps ?? command === 'start';
config.jsxRuntime ??= pkg?.jsxRuntime ?? userConfig.jsxRuntime;
}

/**
* @internal export for test
*/
export function initTask(buildTask: BuildTask, options: InitTaskOptions) {
const { userConfig, rootDir, command } = options;
const { config, name: taskName } = buildTask;
const { pkg } = config;

initSharedTask(buildTask, options);

const expectedMode = command === 'build' ? 'production' : 'development';

if (config.type === 'bundle') {
const bundleConfig = userConfig.bundle ?? {};
config.modes ??= bundleConfig.modes ?? [expectedMode];
// TODO: 判断下这个东西是否真的有用
// Set outputDir to process.env for CI
process.env.ICE_PKG_BUNDLE_OUTPUT_DIR = config.outputDir;
const originMinifyConfig = pkg?.minify ?? bundleConfig.minify ?? defaultBundleUserConfig.minify ?? {};
let { jsMinify, cssMinify } = config;
if (typeof originMinifyConfig === 'object') {
jsMinify ??= getMinifyFunction(originMinifyConfig.js);
cssMinify ??= getMinifyFunction(originMinifyConfig.css);
} else {
jsMinify ??= getMinifyFunction(originMinifyConfig);
cssMinify ??= getMinifyFunction(originMinifyConfig);
}

config.jsMinify = jsMinify;
config.cssMinify = cssMinify;

config.outputDir ??= pkg?.outputDir ?? bundleConfig.outputDir ?? defaultBundleUserConfig.outputDir;

if (pkg) {
mergeDefaults(config, omit(pkg, ['id', 'pluginInfos', 'id', 'target', 'module', 'declaration', 'outputDir']));
}
mergeDefaults(config, bundleConfig);
mergeDefaults(config, defaultBundleUserConfig);
} else if (config.type === 'transform') {
config.modes ??= [expectedMode];
config.outputDir ??= pkg?.outputDir ?? getTransformDefaultOutputDir(rootDir, taskName, config);
} else if (config.type === 'declaration') {
// should run in initDeclarationTask
} else {
throw new Error('Invalid task type.');
}

return buildTask;
}

/**
* 需要判断 entry 是否一致,对于不一致的 entry,理论上要生成多个 declaration task
* @internal export for test
*/
export function initDeclarationTask(buildTask: BuildTask, options: InitTaskOptions, allTasks: BuildTask[]) {
const { userConfig, rootDir } = options;
const { config } = buildTask;
const { declaration: declarationConfig } = userConfig;
if (config.type !== 'declaration') {
throw new Error('initDeclarationTask only allow declaration task');
}
if (declarationConfig === false) {
throw new Error('Cannot disable declaration when transform formats is not empty.');
}
initSharedTask(buildTask, options);
config.outputMode ??=
declarationConfig === true
? defaultDeclarationUserConfig.outputMode
: (declarationConfig.outputMode ?? defaultDeclarationUserConfig.outputMode);
const allOutputDirs = allTasks
.map((v) => {
return v.config.type === 'transform' ? v.config.outputDir! : '';
})
.filter(Boolean);
// 这个 output 仅仅用于生成正确的 .d.ts 的 alias,不做实际输出目录
config.outputDir = allOutputDirs[0];
if (config.outputMode === 'unique') {
config.declarationOutputDirs = [path.resolve(rootDir, 'typings')];
} else {
config.declarationOutputDirs = allOutputDirs;
}

return buildTask;
}

function getMinifyFunction(minify: boolean | ((mode: string, command: string) => unknown)) {
switch (typeof minify) {
case 'boolean':
return () => minify;
case 'function':
return minify;
}
return defaultMinifyFunction;
}
132 changes: 0 additions & 132 deletions packages/pkg/src/core/initContextTasks.ts

This file was deleted.

Loading
Loading