tarojs源码解析(三)/ taro-service

909 阅读3分钟

Kernel

packages/taro-service/src/Kernel.ts

Kernel 是继承 EventEmitter 的一个类。

根据 taro-cli 中对命令行的解析并调用 kernel 可以知道最终是调用了 kernel 的 run 方法,下面我们重点看 run 方法。以 taro build --type weapp -- --watch 为例

  • 【282-294】初始化参数
  • 【295】初始化操作:项目配置、项目路径信息、项目插件;执行完成之后,所有的编译插件、平台编译插件都将挂载到 Kernel实例上,供后续编译程序使用。在装载完成后,将触发 Kernel第一个钩子 - onReady
  • 【297】执行onStart钩子
  • 【301】对 taro [command] -h 帮助命令行做输出。 eg: taro build -h/taro init -h
  • 【313】命令行 type 参数。根据平台类型获取对应编译配置
  • 【322】执行钩子。也就是 kernel.run传入的钩子。build钩子

build 钩子

packages/taro-cli/src/presets/commands/build.ts

注册

  • 调用 Kernel实例的 run 方法会调用 Kernel 实例的 init 方法
  • 调用 initPresetsAndPlugins
  • 调用 initPlugin
  • 调用 packages/taro-cli/src/presets/commands/build.tsregisterCommand完成注册。

执行

kernel.run最后一步调用 applyPlugins执行 build钩子,钩子被触发,最终执行

packages/taro-cli/src/presets/commands/build.ts

  • 【52】检查项目相关配置,这里的配置对应的就是项目中的 config/index.js文件中的配置
  • 【81】构建开始,触发 onBuildStart钩子。taro 官方文档 编译过程扩展 中有对其做介绍。

  • 【82】触发对应平台的钩子。这里是 weapp
  • 【159】构建完成,触发 onBuildComplete钩子。

weapp 钩子

注册

packages/taro-weapp/src/index.ts

执行

packages/taro-cli/src/presets/commands/build.ts

  • 【82】行执行了ctx.applyPlugins, 调用 weapp钩子。
  • 【16】获取 Weapp 实例

Weapp: packages/taro-weapp/src/program.ts

TaroPlatformBase: packages/taro-service/src/platform-plugin-base.ts

  • 【17】执行实例的 start方法:packages/taro-service/src/platform-plugin-base.ts

【191】setup

  1. 【76】清空 dist 文件夹
  2. 【78-80】输出编译提示
  1. 【82】生成 project.config.json

【192】build 调用 mini-runner 开始编译

  • 【147】const runner = await this.getRunner(),加载 miniRunner
    • 【115】获取当前项目内的 @tarojs/mini-runner
  • 【148】准备 miniRunner 配置参数
  • 【152】运行 miniRunner

mini-runner

可以看到实际上,最终就是运行了 webpack。

webpackConfig【40】 是 【37】通过 webpackChain.toConfig()

/mini-runner/src/index.ts

/mini-runner/src/webpack/build.conf.ts

/mini-runner/src/webpack/chain.ts

/mini-runner/src/plugins/BuildNativePlugin.ts

/mini-runner/src/plugins/MiniPlugin.ts

TaroMiniPlugin也就是小程序编译的核心部分

  • 【326】compiler 钩子 - emit:输出 assets 到 output 目录之前执行。这个钩子不会被复制到子编译器。
  • 【329】生成小程序相关文件

webpack相关

taro 使用 webpack4

可以看到编译vue => 小程序核心是使用 compiler.hooks + assets 实现生成小程序相关文件。

以下 demo 模拟了这一过程:

const webpack = require('webpack')
const path = require('path')
const config = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  }
}

const tryAsync = fn => async (arg, callback) => {
  try {
    await fn(arg)
    callback()
  } catch (err) {
    callback(err)
  }
}

async function generateMiniFiles(compilation) {
  const fileConfigName = 'app.json'
  const fileConfigStr = `
{
  "pages": ["pages/index/index"],
  "window": {
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "WeChat",
    "navigationBarTextStyle": "black"
  },
  "usingComponents": {}
}
  `
  compilation.assets[fileConfigName] = {
    size: () => fileConfigStr.length,
    source: () => fileConfigStr
  }
}

const compiler = webpack(config)

compiler.hooks.emit.tapAsync(
  'TaroMiniPlugin',
  tryAsync(async compilation => {
    await generateMiniFiles(compilation)
  })
)

const watching = compiler.watch(
  {
    aggregateTimeout: 300,
    poll: undefined
  },
  async (err, stats) => {
    if (err || stats.hasErrors()) {
    }
  }
)
  • 【40】生成 compilation 实例
  • 【42】注册钩子 emit
  • 【45】触发钩子,执行 generateMiniFiles
    • 【21-33】定义 assets 文件和内容
    • 【34】为 compilation.assets 添加内容

最终生成 app.json 文件并写入内容。