1.x | 0.x
基于 Webpack 的插件化工程构建工具,支持快速建设一套开箱即用的工程方案。
build-scripts
还是 @alib/build-scripts
?1.x 以及未来都以 build-scripts
为准,0.x 版本当时因为命名被占用只能使用 @alib/build-scripts
这个包名。
参考 版本升级 章节。
多个项目共享 Webpack 以及其他工程能力,同时支持插件扩展&修改配置。
基于 build-scripts 目前已支持多种场景,覆盖大多数的研发场景,当然你可以完全自定义一套工程能力。
仅阿里内部
如果不想使用上述官方提供的解决方案,也可以基于 build-scripts 自定义完整的工程能力,具体请参考 example 。
build-scripts 核心支持了 start、build 和 test 三个命令。
$ build-scripts start --help
Usage: build-scripts start [options]
Options:
--port <port> 服务端口号
--host <host> 服务主机名
--config <config> 自定义配置文件路径(支持 json 或者 js,推荐命名 build.config.js/build.json)
$ build-scripts build --help
Usage: build-scripts build [options]
Options:
--config <config> 同 start
$ build-scripts test --help
Usage: build-scripts test [options]
Options:
--config <config> 同 start
build-scripts 默认将 build.json
作为工程配置文件,运行 build-scripts 命令时会默认读取当前目录的 build.json
文件。
配置方式:
{
"externals": {
"react": "React"
},
"plugins": [
"build-plugin-component",
"./build.plugin.js"
]
}
build.json 中核心包括两部分内容:
externals
字段,默认情况下不支持任何字段,由基础插件通过 registerUserConfig
API 注册扩展除了 json 类型以外,build-scripts 也支持 js 类型的配置文件:
// build.plugin.js
module.exports = {
plugins: []
}
然后通过 --config
参数指定即可 build-scripts start --config build.config.js
。
通过 build.json
中提供的 plugins 字段可配置插件列表,插件数组项每一项代表一个插件,build-scripts 将按顺序执行插件列表,插件配置形式如下:
{
"plugins": [
// 数组第一项为插件名,第二项为插件参数
["build-plugin-fusion", {
"themePackage": "@icedesign/theme"
}]
]
}
如果基础配置和已有插件都无法支持业务需求,可以通过本地插件自定义配置来实现,新建 build.plugin.js
文件作为一个自定义插件,然后写入以下代码:
module.exports = ({ context, onGetWebpackConfig }) => {
// 这里面可以写哪些,具体请查看插件开发章节
onGetWebpackConfig((config) => {
});
}
最后在 build.json
里引入自定义插件即可:
{
"plugins": [
"build-plugin-component",
"./build.plugin.js"
]
}
通过命令创建一个插件 npm 包:
$ npm init npm-template <pluginName> build-plugin-template
$ cd <pluginName>
插件本质上是一个 Node.js 模块,入口如下:
module.exports = ({ context, onGetWebpackConfig, log, onHook, ...rest }, options) => {
// 第一项参数为插件 API 提供的能力
// options:插件自定义参数
};
插件方法会收到两个参数,第一个参数是插件提供的 API 接口和能力,推荐解构方式按需使用 API,第二个参数 options 是插件自定义的参数,由插件开发者决定提供哪些选项给用户自定义。
插件可以方便扩展和自定义工程能力,这一切都基于 build-scripts 提供的插件 API。
context 参数包含运行时的各种环境信息:
command
当前运行命令 start|build|test
commandArgs
script 命令执行时接受到的参数rootDir
项目根目录originalUserConfig
用户在 build.json 中配置的原始内容userConfig
用户配置,包含被 modifyUserConfig 修改后的结果pkg
项目 package.json 的内容webpack
webpack 实例,插件中针对 webpack 的逻辑均使用此方式引入module.exports = ({ context }) => {
const { userConfig, command, webpack } = context;
console.log('userConfig', userConfig);
console.log('command', command);
};
通过 onGetWebpackConfig
获取 webpack-chain 形式的配置,并对配置进行自定义修改:
// 场景一:修改所有 webpack 配置
module.exports = ({ onGetWebpackConfig }) => {
onGetWebpackConfig((config) => {
config.entry('src/index');
});
}
// 场景二:多 webpack 任务情况下,修改指定任务配置
module.exports = ({onGetWebpackConfig, registerTask}) => {
registerTask('web', webpackConfigWeb);
registerTask('weex', webpackConfigWeex);
onGetWebpackConfig('web',(config) => {
config.entry('src/index');
});
onGetWebpackConfig('weex',(config) => {
config.entry('src/app');
});
}
通过 onHook 监听命令运行时事件,onHook 注册的函数执行完成后才会执行后续操作,可以用于在命令运行中途插入插件想做的操作:
module.exports = ({ onHook }) => {
onHook('before.start.load', () => {
// do something before dev
});
onHook('after.build.compile', stats => {
// do something after build
});
};
目前的命令执行生命周期如下:
start 命令:
生命周期 | 参数 | 调用时机 |
---|---|---|
before.start.load | { args: CommandArgs; webpackConfig: WebpackConfig[] } | 获取 webpack 配置之前 |
before.start.run | { args: CommandArgs; webpackConfig: WebpackConfig[] } | webpack 执行构建之前 |
after.start.compile | { url: string; stats: WebpackAssets; isFirstCompile: boolean } | 编译结束,每次重新编译都会执行 |
before.start.devServer | { url: string; devServer: WebpackDevServer } | server 中间件加载后,webpack devServer 启动前 |
after.start.devServer | { url: string; devServer: WebpackDevServer } | webpack devServer 启动后 |
build 命令:
生命周期 | 参数 | 调用时机 |
---|---|---|
before.build.load | { args: CommandArgs; webpackConfig: WebpackConfig[] } | 获取 webpack 配置之前 |
before.build.run | { args: CommandArgs; webpackConfig: WebpackConfig[] } | webpack 执行构建之前 |
after.build.compile | { url: string; stats: WebpackAssets; isFirstCompile } | 编译结束 |
test 命令:
生命周期 | 参数 | 调用时机 |
---|---|---|
before.test.load | { args: CommandArgs; webpackConfig: WebpackConfig[] } | 获取 jest 配置之前 |
before.test.run | { args: CommandArgs; config: JestConfig } | jest 执行构建之前 |
after.test | { result: JestResult } | 测试结束 |
build-scripts 统一的 log 工具,底层使用 npmlog ,便于生成统一格式的 log:
module.exports = ({ log }) => {
log.verbose('verbose');
log.info('info');
log.error('error');
log.warn('warn');
};
通过 registerUserConfig 注册 build.json 中的顶层配置字段,注册是可以进行用户字段校验,支持传入单个配置对象或者包含多个配置对象的数组。
方法生效的生命周期,在 registerTask 和 onGetWebpackConfig 之间。
配置对象字段如下:
字段名称,唯一标识,多个插件无法注册相同的字段保留字段:plugins
字段校验,支持 string 快速校验,string|boolean|number,也可以自定义函数,根据 return 值判断校验结果
配置忽略指定 webpack 任务
字段效果,具体作用到 webpack 配置上,接收参数:
module.exports = ({ registerUserConfig }) => {
registerUserConfig({
name: 'entry',
// validation: 'string',
validation: value => {
return typeof value === 'string';
},
configWebpack: (config, value, context) => {
config.mode(value);
},
});
};
用于注册多 webpack 任务,比如 build-plugin-react-app 上已完整支持 React 链路开发,大部分情况下在默认 webpack 任务上拓展即可,无需额外注册.
// 注册的 config 必须是以 webpack-chain 形式组织
module.exports = ({ registerTask }) => {
registerTask('web', webpackConfigWeb);
registerTask('component', webpackConfigComponent);
};
用于取消已注册任务
module.exports = ({ cancelTask }) => {
cancelTask('web');
};
判断 build.json 中的顶层配置字段或者 cli 参数是否已经注册:
module.exports = ({ hasRegistration }) => {
// 判断 build.json 顶层配置字段 entry 是否已配置
const hasEntryRegistered = hasRegistration('entry');
// 判断 cli --https 参数是否已被注册
const hasHttpsRegistered = hasRegistration('https', 'cliOption');
...
}
用于修改已注册用户配置的行为:
module.exports = ({ modifyConfigRegistration }) => {
modifyConfigRegistration('name', configRegistration => {
return {
...configRegistration,
// 修正验证字段
validation: 'string',
};
});
};
通过 modifyUserConfig 可以修改通过 registerUserConfig 注册的基础配置,在插件中快速复用基础配置的处理逻辑:
module.exports = ({ modifyUserConfig }) => {
modifyUserConfig(originConfig => {
// 通过函数返回批量修改
return { ...originConfig, define: { target: 'xxxx' } };
});
};
通过指定具体修改的基础配置,快速完成配置的修改:
module.exports = ({ modifyUserConfig }) => {
modifyUserConfig('entry', 'src/app');
// 通过对象路径修改,比如修改对象 { outputAssetsPath: { js: 'js-dist'} } 可通过以下方式
modifyUserConfig('outputAssetsPath.js', 'js');
// 支持深合并,默认情况下 modifyUserConfig 将覆盖原有配置,通过配置参数支持配置的合并
modifyUserConfig('outputAssetsPath', {
js: 'js-output'
}, { deepmerge: true });
};
API 执行的生命周期:所有插件对于修改配置函数将保存至 modifyConfigRegistration 中,在 runUserConfig 执行前完成对当前 userConfig 内容的修改
注册各命令上支持的 cli 参数,比如 npm start --https 来开启 https:
module.exports = ({ registerCliOption }) => {
registerCliOption({
name: 'https', // 注册的 cli 参数名称,
commands: ['start'], // 支持的命令,如果为空默认任何命令都将执行注册方法
configWebpack: (config, value, context) => {
// 对应命令链路上的需要执行的相关操作
},
});
};
注册函数执行周期,在 userConfig 相关注册函数执行之后。
用于修改已注册 cli 配置的行为:
module.exports = ({ modifyConfigRegistration }) => {
modifyCliRegistration('https', cliRegistration => {
return {
...cliRegistration,
// 修正 commands 字段
commands: ['start'],
};
});
};
用于获取所有注入任务的名称:
module.exports = ({ getAllTask }) => {
const taskNames = getAllTask();
// ['web', 'miniapp']
};
在一些业务场景下,插件间需要进行通信:
基于上述的诉求,API 层面提供 setValue
和 getValue
来用于数据的存取,registerMethod
和 applyMethod
来解决方法的复用。
用来在 context 中注册变量,以供插件之间的通信。
module.exports = ({ setValue }) => {
setValue('key', 123);
};
用来获取 context 中注册的变量。
module.exports = ({ getValue }) => {
const value = getValue('key'); // 123
};
向工程核心注册相关方法,方便其他插件进行复用:
module.exports = ({ registerMethod }) => {
// 注册方法
registerMethod('pipeAppRouterBefore', content => {
// 执行相关注册逻辑,可以返回相应的值
return true;
});
};
registerMethod 注册方式时,通过参数指定可以获取调用该方法的具体插件名:
module.exports = ({ registerMethod }) => {
// 注册方法
registerMethod('pipeAppRouterBefore', (pluginName) => (content) => {
console.log('plugin name', pluginName);
console.log('content', content);
// 执行相关注册逻辑,可以返回相应的值
return true;
}, { pluginName: true });
};
调用其他插件的注册方法
module.exports = ({ applyMethod }) => {
// 使用其他差价注册方法的方式,如果插件未注册,将返回一个 error 类型的错误
// 类似 new Error(`apply unkown method ${name}`)
const result = applyMethod('pipeAppRouterBefore', 'content');
};
1.x 核心变化:
@alib/build-scripts
切换为 build-scripts
string | object | array
校验除了前两点属于不兼容改动,其他能力都保持向前兼容。
在 package.json 中增加依赖:
{
"devDependencies": {
+ "jest": "^26.4.2",
+ "webpack": "^4.27.1",
+ "webpack-dev-server": "^4.0.0",
- "@alib/build-scripts": "^0.1.0",
+ "build-scripts": "^1.0.0",
}
}
其中 jest 可按需判断是否需要安装,webpack 版本按需选择。修改完成后重装依赖然后重启即可。
升级 icejs 2.0. 即可。
待支持
在 package.json 中升级依赖:
{
"devDependencies": {
- "@alib/build-scripts": "^0.1.0",
+ "build-scripts": "^1.0.0",
- "build-plugin-component": "^1.0.0",
+ "build-plugin-component": "^1.6.5",
}
}
build-plugin-component 从 1.6.5 开始同时兼容 build-scripts 0.x 和 1.x 两个版本
待支持
https://www.jianshu.com/p/630206347112 简介 build.gradle是gradle中非常重要的一个文件,因为它描述了gradle中可以运行的任务,今天本文将会带大家体验一下如何创建一个build.gradle文件和如何编写其中的内容。 project和task gradle是一个构建工具,所谓构建工具就是通过既定的各种规则,将原代码或者原文件通过一定的tas
‘react-scripts’ 不是内部或外部命令,也不是可运行的程序 或批处理文件。 报这种错误的时候可以重新装 yarn add react-scripts 然后重启项目就可以了,赶快试试吧!!! yarn start [巴拉巴拉]
create-react-app创建的React项目时,有时在安装完其他组件后,再次运行 npm start 命令时会报以上错误,让我很郁闷,不过在上网搜了这个错后原来: 是create-react-app有丢包的缺陷,手动安装包后,需要重新npm install一下,这样node_modules/.bin/目录下才会重新出现react-scripts的文件,这样npm start命令才能正常执行
如果npm install报错,单独安装这个包,加上参数:–ignore-scripts npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! deasync@0.1.21 install: `node ./build.js` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the deasync
关于GENERATE_SOURCEMAP的作用原理在这篇文章中介绍过。 create-react-app :不产生source-map来缩减打包文件体积 可以通过创建.env环境变量文件影响react-scripts start/build等命令。其实还有另一种更灵活的方式设置环境变量,使用export可以对不同的命令设置不同的环境变量. 打开package.json,找到scripts配置项
简介 build.gradle是gradle中非常重要的一个文件,因为它描述了gradle中可以运行的任务,今天本文将会带大家体验一下如何创建一个build.gradle文件和如何编写其中的内容。 project和task gradle是一个构建工具,所谓构建工具就是通过既定的各种规则,将原代码或者原文件通过一定的task处理过后,打包生成目标文件的步骤。 所以我们在gradle中有两个非常重要的
官网用法 用法:vue-cli-service build [options] [entry|pattern] 选项: --mode 指定环境模式 (默认值:production) --dest 指定输出目录 (默认值:dist) --modern 面向现代浏览器带自动回退地构建应用 --target app | lib | wc
import "go/build" Package build gathers information about Go packages. Go Path ¶ The Go path is a list of directory trees containing Go source code. It is consulted to resolve imports that cannot
Netlify Build runs the build command and Build Plugins and bundles Netlify Functions. Build Plugins extend the functionality of the Netlify Build process. You can install plugins made by others or wri
构建命令,用于渲染您的 md,并输出静态 html: mdbook build 它会尝试解析你的SUMMARY.md文件,以了解您的图书的结构并获取相应的文件. 为方便起见,渲染的输出将保持与源目录结构相同。因此,大型书籍在渲染时能保持结构化. build命令可以将目录作为参数,用作本书的根目录,而不是当前工作目录. mdbook build path/to/book 当你使用--open(-
NPM tasks Running your first build The build process is using Webpack, Babel and as well as npm tasks listed in package.json. During this process, the source located in the src/* directory are transfo
build 用法 Usage: docker build [OPTIONS] PATH | URL | - Build a new image from the source code at PATH -f, --file="" Name of the Dockerfile (Default is 'PATH/Dockerfile') --force-rm=false
go build命令用于编译我们指定的源码文件或代码包以及它们的依赖包。 例如,如果我们在执行go build命令时不后跟任何代码包,那么命令将试图编译当前目录所对应的代码包。例如,我们想编译goc2p项目的代码包logging。其中一个方法是进入logging目录并直接执行该命令: hc@ubt:~/golang/goc2p/src/logging$ go build 因为在代码包logging