Remax 所有构建类所继承的抽象类 Builder

504 阅读4分钟

remax中所有构建类都要继承抽象类Builder中的方法,实现runbuildwatchcreateWebpackConfig方法,并且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)

该方法会保存配置,并加载指定的参数。

保存配置到当前构建实例

通过方法入参给当前编译类参数apioptionstargetbuildType赋值

加载平台适配插件

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配置。