remax中所有构建类都要继承抽象类Builder中的方法,实现run、build、watch、createWebpackConfig方法,并且constructor中定义了所有需要的初始化信息。文件存在于/remax/packages/remax-cli/src/build/Builder.ts
Builder中的参数
/**
* 公共API
*/
api: API;
/**
* remax配置
*/
options: Options;
/**
* 平台
*/
target: Platform;
/**
* 项目公共路径
*/
projectPath: ProjectPath;
/**
* 项目配置
*/
projectConfig: AppConfig | MiniPluginConfig;
/**
* 各种入口控制中心
*/
entryCollection: EntryCollection;
/**
* webpack 编译器
*/
webpackCompiler: webpack.Compiler;
/**
* 构建类型
*/
buildType: BuildType;
/**
* webpack 配置
*/
webpackConfig: any;
constructor 的内容
constructor(api: API, options: Options, buildType: BuildType)
该方法会保存配置,并加载指定的参数。
保存配置到当前构建实例
通过方法入参给当前编译类参数api、options、target、buildType赋值
加载平台适配插件
if (this.target !== 'web') {
api.registerAdapterPlugins(this.target);
}
除了web端,其他平台加载适配插件,通过加载适配插件中的 /src/node/index.ts文件达到适配不同平台的目的。
该文件会指定下面的配置:
- 全局变量
- 视图层模板文件类型和引入方式
- 视图层样式文件类型
- 视图层脚本语言文件类型和引入方式
- ejs模板文件路径指定
- 平台主要组件
- 不需要编译的组件
- staticEjs模板文件路径指定
初始化项目路径
this.projectPath = new ProjectPath(this)
/remax/packages/remax-cli/src/build/ProjectPath.ts
使用当前builder实例中的配置,获取并返回对应的文件或者文件夹路径,返回的路径需要使用 slash(/remax/packages/remax-shared/src/path.ts) 统一格式化为斜线。
其中方法包括:项目根路径、打包路径、src路径、public静态文件路径、app.config.js文件路径、plugin.config.js文件路径、src下指定文件名路径、组件配置文件路径、各种引入文件路径识别、搜索文件是否存在(优先匹配多平台支持文件)等,所有方法都会返回一个路径。
多平台文件类型在/remax/packages/remax-cli/src/extensions.ts中定义,并且ui优先匹配多平台支持文件,当查找到文件后直接返回,不继续查找
加载项目配置
this.projectConfig = this.fetchProjectConfig()
- 加载项目配置文件路径,获当前发布平台指定配置文件,没有则读取默认文件
- 根据发布的平台读取配置文件,通过
readManifest读取当前发布平台module.exports.xxx = {}没有则读取module.export = {} - 执行所有onAppConfig钩子函数,修改应用配置并返回新的config
根据上面描述项目配置加载顺序是:先平台指定配置文件、默认配置文件、配置文件中平台导出、配置文件中默认导出
加载各种入口
this.entryCollection = new EntryCollection(this)
this.entryCollection.init()
根据当前构建类实例会首先加载 项目入口、app.config.js 中插件面向第三方小程序的 js 接口、各个页面入口,/remax/packages/remax-cli/src/build/EntryCollection.ts。
init() {
// 加载入口文件 src/app.js
this.appEntry = this.initAppEntry();
// 加载app.config.js 中插件面向第三方小程序的 js 接口
this.mainEntry = this.initMainEntry();
// 加载各个页面入口
this.entries = this.initEntries();
}
加载项目入口 src/app.js
加载app.config.js 中插件面向第三方小程序的 js 接口
加载各个页面入口
获取webpack配置
this.webpackConfig = this.createWebpackConfig()
此方法是一个抽象方法,需要各构建类自行实现。
获取webpack编译器
this.webpackCompiler = this.createWebpackCompiler()
根据webpack的配置获取编译器
各抽象方法
所有抽象方法都需要实现,并且默认运行方法是run方法。
run
构建类运行的指定方法,这里主要用来判断是运行build方法、还是运行watch方法,最后返回webpack编译器。
build
调用webpack编译器的run方法,仅仅构建一次。
watch
调用webpack编译器的watch方法,监听文件变化,当出现变化时重新编译。
同时还存在一些不会被监听器监听的文件,这时就需要手动监听再进行重新编译;/remax/packages/remax-cli/src/build/watch.ts 这里使用 chokidar实现了这些功能。当然什么时候需要监听特定文件,由各个构建类内部决定
- 监听根目录
app.config.{js,ts}文件,当出现变化时进行如下操作:- 重新加载项目配置
- 重置各种入口
- 各个页面入口强制更新
- 更新webpack编译器
- 强制更新源代码
- 重新动态添加构建入口
- 结束当前编译循环(compiling round),而不停止监视进程,并重新编译
- 监听各页面
app.config.{js,ts}文件,当出现变化时进行如下操作- 结束当前编译循环(compiling round),而不停止监视进程,并重新编译
watchRun钩子标记编译进行中,防止重复触发编译done钩子标记编译结束,可以进行下一次编译
createWebpackConfig
返回各构建类各自所特有的webpack配置。