build-scripts icon indicating copy to clipboard operation
build-scripts copied to clipboard

[RFC] build-scripts 2.0 版本设计

Open maoxiaoke opened this issue 3 years ago • 3 comments

背景

  • build-scripts 与 webpack 体系解耦,沉淀为底层插件开发服务。

方案

build-scripts 分层设计

image

Service 规范

Service 确定如何实现诸如 startbuild 的命令,可以是由函数或类实现,比如(以 webpack 为例):

import { Service } from 'build-scripts';
import start from './start';
import build from './build';
import WebpackChain from 'webpack-chain';
import webpack from 'webpack';

const webpackService = new Service<WebpackChain, Record<'webpack', typeof webpack>>({
	name: 'webpack',
	command: {
		start,
		build
	},
	bundlers: {
		wepback
	}
})

export default webpackService;

// start.ts 实现 npm run start
// build.ts 实现 npm run build
// 参考实现如下
export default start = (context: Context<WebpackChain>) => {
	const { getConfig, applyHook } = context;
	const configArr = context.getConfig();

	await applyHook(`before.${command}.load`, { xxx })

	try {
		compiler = webpackInstance(webpackConfig);
	} catch (e) {
		await applyHook('error', { err });
	}

	compiler.run((err, stats) => {
		// 
	})

	await applyHook(`after.${command}.compile`, result)
}

Service API

Service 可消费 Context 的所有 public API:

interface Context {
	command: 'build' | 'start' | 'test',
	commandArgs: object;
	rootDir: string;
	pkg: Json;
	applyHook: (key: string, opts?: {}) => Promise<void>;
	logger: Logger;
	...
}

插件 API

插件 API 与现有插件 api 基本保持一致(除部分存在命名上变更)。主要变更有:

  • onGetWebpackConfig → 变更为 onGetConfig,使用方式保持与之前不变
// 入参 config 与 registerTask 配置 对应
interface onGetConfig<T> {
	(name: string, fn: (config: T)): void;
	(fn: (config: T)): void;
}
  • registerTask 入参变更
    • 对于 webpack,注册的是 wepback-chain
    • 对于 vite,注册的是 vite config (目前对于 ice 来说,通过单一插件支持,因此注册的仍是 webpack-chian,通过一层 webpack2vite 进行了磨平)
    • 对于 rollup,注册的是 rollup 配置
  • ctx 不再默认导出 webpack

之前存在从 ctx 下导出 wepback 的场景,目的是保证使用的是统一 webpack 实例。新模式下,需要 Service 注入给 Plugin 消费。

const ctx = createContext({
	command: 'start',
	rootDir: this.options.rootDir,
	bundlers: {
		webpack
	}
})
  • configWebpack 字段修改为 setConfig,入参为 Task Config。

注册 Task

Task 通过插件注册,注册方式如下:

const plugin = ({
	registerTask
}) => {
	// 以 webpack 为例,注册 webpack-chain 配置
	registerTask('taskName', webpackConfig);
}

具体改动

  • Context API 变更

    • [x] 移除 publicAPI registerCommandModules
    • [x] 移除 publicAPI getCommandModule
    • [x] 移除 pulicAPI getWebpackConfig
    • [x] 移除 privateAPI getProjectFile - 移进 utils 文件夹,修改名为 loadPkg
    • [x] 修改 onHook 方法为 privateAPI
  • 依赖包升级

  • Service 可消费的 api

    • command
    • commandArgs
    • rootDir
    • pkg
    • userConfig

maoxiaoke avatar Jan 06 '22 03:01 maoxiaoke

建议补充下 现有 webpack 体系在新架构下涉及到哪些 API 需要定制,已经定制逻辑中的伪代码

ClarkXia avatar Jan 06 '22 06:01 ClarkXia

对于 getConfig,最好增加标识看下当前是 webpack 还是 rollup,避免webpack4 => 5的恶心的兼容

denghongcai avatar Jun 13 '22 07:06 denghongcai

对于 getConfig,最好增加标识看下当前是 webpack 还是 rollup,避免webpack4 => 5的恶心的兼容

指的是在配置层面能够感知 具体是 webpack 还是 rollup? getConfig 上的 config 具体包含哪些配置主要由上层工具决定,比如 ice/pkg 和 icejs

ClarkXia avatar Jun 13 '22 08:06 ClarkXia