什么是Taro

Taro 是一套遵循多端开发的解决方案。只需要一套代码,就可以编译转换成 RN、H5、小程序、快应用多端的运行代码,其运转流程主要分为编译时,运行时两个阶段。

Taro2(重编译,轻运行)

  • 编译时:通过taro工具将Taro源代码转换成目标代码
  • 运行时:目标代码运行时,通过运行时的库去适配不同端

图片

Taro3(轻编译,重运行)
Taro3主要通过在小程序端模拟实现 DOM、BOM API 来让前端框架直接运行在小程序环境中,而对于生命周期、组件库、API、路由等差异,通过定义统一标准,在运⾏时会提供 React 和 Vue 对应的适配器进⾏适配,然后调⽤Taro提供的 DOM 和 BOM API, 最后把整个程序渲染到所有的⼩程序端上⾯。

图片

编译流程

Taro本质上是进行多端编译和运行,而Taro的编译主要依赖于webpack配置,Taro则通过mini-runner完成webpack配置的组装,然后根据 webpack 配置生成编译后的代码。

tarojs/mini-runner的作用

  • 负责根据开发者的编译配置调整 webpack 配置
  • 注入自定义的 插件 和 loader
  • 调用 webpack 开启编译
  • 修改 webpack 的编译产物,调整最终的编译结果

图片

目录结构

图片

主流程(index)

主要分为两个流程,根据项目配置生产webpack的构建配置,利用webpack进行代码编译。

图片

基础配置

base.config.ts 文件记录基本配置信息,主要是Taro 构建过程中一部分 webpack 配置的初始化工作(包括文件扩展名、模块解析路径、别名等)。

图片

自定义配置

buildConf.conf.ts 中主要负责配置一些构建过程中所需的插件、常量和选项,确保构建过程中能够根据配置进行适当的处理和优化。

图片

合并webpack配置

合并webpack配置,确保小程序项目在构建时能够按照用户的配置和需求生成合适的 Webpack 配置。

图片

分析配置

通过分析主包来进一步了解tarojs/mini-runner在其中的作用。

图片

查看config配置

图片

  • projectName: 项目名称
  • date: 项目创建日期
  • designWidth: 设计稿宽度,用于进行适配
  • deviceRatio: 不同设备宽度的适配比例
  • sourceRoot: 源代码目录
  • outputRoot: 输出目录,根据环境变量进行不同的配置
  • plugins: 配置Taro框架使用的插件
  • env: 环境变量配置
  • defineConstants: 常量配置
  • copy: 复制文件的配置,将一些静态文件复制到输出目录
  • framework: 项目框架
  • mini: 针对小程序的配置
  • h5: 针对H5平台的配置
  • alias: 路径别名配置,简化在代码中的引用路径

defineConstants

defineConstants 主要进行常量的相关配置。

图片

首先将环境变量,静态常量,运行时常量合并为一个常量对象definePlugin,通过getDefinePlugin 函数返回了一个配置好的 DefinePlugin 实例,definePlugin是Webpack的一个内置插件,用于替换代码中的变量为其对应的值。

通过这个配置,Webpack 在构建时会将代码中的 APPNAME 替换为 process.env.APPNAME 的值。同样,其他常量也会按照相应的方式被替换。

图片

copy

copy复制文件的配置,将一些静态文件复制到输出目录,

  • patterns: 一个数组,指定了需要拷贝的文件或目录的规则
  • options: 配置选项

图片

不同环境拷贝不同的目标路径,主要用于对地图的适配。

图片

在 patterns 数组中添加了一个额外的拷贝规则,将 plugin/doc 目录拷贝到输出目录的 doc 目录下,如果配置中存在copy 调取getCopyWebPackPlugin。

图片

getCopyWebpackPlugin 函数接收一个包含 copy 配置的对象以及应用程序路径 appPath。通过 CopyWebpackPlugin 创建实例,配置 patterns,将配置项中的相对路径转换为绝对路径,确保正确的拷贝。返回创建的 CopyWebpackPlugin 实例。

图片

alias

alias主要用于简化在代码中的引用路径。

图片

resolve 是一个配置选项,用于指定解析模块请求的规则。alias 配置会被合并到 resolve 中。

在构建过程中,Webpack 将会使用这些别名来解析模块的引入路径。例如,当代码中出现 import '@/ecoExpress/someModule' 时,Webpack 将会解析为 path.resolve(__dirname, '..', 'src/ecoExpress/someModule')。

图片

mini

postcss

pxtransform 配置:

  • enable: true 表示开启对 CSS 中的 px 单位进行转换
  • config: 可以用于配置 pxtransform 的详细选项,比如配置项的转换规则
    url 配置:
  • enable: true 表示开启对样式文件中的图片、字体等资源的 URL 转换
  • config: { limit: 1024 } 限制转换的资源大小,超过这个大小的资源将被单独输出文件,小于这个大小的资源将被转换成 base64 编码并嵌入样式文件中

这个配置的目的是将小图片、字体等资源直接转换成 base64 编码,减少网络请求,提高小程序的加载速度。
cssModules 配置:

  • enable: false 表示不开启 CSS Modules 功能。
  • config: 可以配置一些关于 CSS Modules 的选项,包括命名规则等

开启了 CSS Modules,可以通过配置项进行定制化,CSS Modules 允许将 CSS 样式作用域限制在组件内,避免全局样式的污染。

图片

查看config基础配置,进行了一些预处理。

图片

webpackChain

在 webpack 中,webpackChain 通常指的是一种链式调用的方式来配置 Webpack 的构建过程。在 Taro 中,webpackChain 主要是用于自定义和扩展 Webpack 配置的工具。

Taro 封装了 webpack 的配置,提供了一些默认的配置,同时也允许开发者通过 webpackChain 自定义和扩展这些配置。这种链式调用的方式可以更方便地对 Webpack 配置进行修改和增强。

如下代码可知,mini-runner 将内部 webpackChain 和开发者配置的 webpackChain 相结合,得到最终的webpackChain。

图片

针对小程序进行配置。

图片

先查看mini中的webpackChain,查看第一个插件 hitchFeCompontsImportPlugin,可以得出主要功能是匹配不同依赖路径确定不同的配置。

图片

multiPlatformPlugin,接着看下一个函数,这个方法的作用是为 Taro 项目配置 Webpack 的解析插件,限制只解析以 '@hb/' 开头的模块路径,以支持 Taro 项目的多平台打包需求。

图片

使用 webpack-bundle-analyzer 插件,并传递一个空数组 [] 作为配置(webpack-chain中 use的第二个参数,作为插件的配置,可以不填,但必须要是数组)。

图片

使用自定义的 Stats 类创建的插件。这个插件的作用是在 Webpack 构建完成后将统计信息写入一个文件(stats.json),以供进一步分析和处理。

图片

  • 使用 chain.optimization 配置 Webpack 的优化
  • 调用 .minimizer() 方法,传递一个包含 TerserPlugin 实例的数组。TerserPlugin 用于压缩 JavaScript 代码
  • extractComments: false,配置了禁止提取注释的选项,以防止将注释提取到单独的文件中

图片

optimizeMainPackage

配置项 optimizeMainPackage 控制了主包的优化,只有在构建目标环境是微信小程序(TARO_ENV === 'weapp')时才启用。主要的目的是在微信小程序中优化主包的构建。

图片

判断 optimizeMainPackage.enable 是否为 true,如果为 true,则使用 getMiniSplitChunksPlugin 函数创建了一个插件实例,并将其配置合并了 optimizeMainPackage 和 fileType。这个插件的作用是对小程序主包进行分包优化。

图片

Webpack 提供了 SplitChunkPlugin 进行分包优化。SplitChunksPlugin 插件可以将应用程序中共享的代码拆分成单独的块,以便将其从应用程序代码中分离出来,从而提高性能和加载速度。

miniCssExtractPluginOption

miniCssExtractPluginOption用于指定 Mini CSS Extract 插件的选项。,其中 ignoreOrder 主要是为了避免关于样式引入顺序的警告。当为 true 时,表示忽略 CSS 文件的引入顺序,不会抛出关于引入顺序的警告。

图片

baseLevel

对于不支持模板递归的小程序(微信、QQ、京东小程序),在 DOM 层级达到一定数量后,Taro 会使用原生自定义组件协助递归。

简单理解就是 DOM 结构超过 N 层后,会使用原生自定义组件进行渲染。N 默认是 16 层,可以通过修改配置项 修改 N。

H5

再查看下H5中webpackChain的作用

图片

首先跟小程序配置类似,先调用multiPlatformPlugin这个方法的作用是为 Taro 项目配置 Webpack 的解析插件,限制只解析以 '@hb/' 开头的模块路径,以支持 Taro 项目的多平台打包需求。

然后chain.module.rules.get('script').exclude.clear().add([...]);:这一段代码涉及到对 Webpack 规则的修改

  • chain.module.rules.get('script') 表示获取名为 'script' 的规则
  • exclude.clear() 清空原有的排除规则
  • add([...]) 添加新的排除规则,其中传入的函数用于判断是否应该排除某个文件

这个规则的目的是排除一些特定的文件,包括 @tarojs/components 目录下的文件,以满足一定条件的 node_modules 下的文件,但不包括包含 taro 和 @hb/ 的文件。为了定制 Taro 在 H5 平台的构建规则。

图片

然后调用hitchFeCompontsImportPlugin。

图片

总结

总的来说在编译方面,mini-runner 支持多端开发,使开发者能够通过一套代码适配不同的小程序平台。还提供了默认的构建配置,包括 loader、plugin、resolve 规则等,以满足 Taro 框架的开发需求,并允许开发者通过配置文件或插件进行对构建过程的定制和扩展。

在对webpack配置方面,mini-runner 提供了webpackChain方法,使得开发者可以在 Webpack 配置中进行链式调用,方便自定义和增强配置。封装了一套默认的 Webpack 配置,以适应 Taro 框架的特性和小程序平台的要求。此外,mini-runner 控制构建过程,提供一些配置项,例如是否监听文件变化、是否启用 source map 等。

附录 - (mini-runner 部分源码解析)

目录结构

图片

主流程(index)

主要分为两个流程,根据项目配置生产webpack的构建配置,利用webpack进行代码编译。

图片

基础配置

进入 buildConf 函数,由代码可知,首先调用了 getBaseConf ,进入该函数查看配置。

图片

查看该配置,主要是Taro 构建过程中一部分 webpack 配置的初始化工作(包括文件扩展名、模块解析路径、别名等)。通过配置解析选项和引入 MultiPlatformPlugin 插件,支持跨平台文件。

  • 源文件使用的扩展名,这里包括 '.js', '.jsx', '.ts', '.tsx', '.mjs', '.vue'
  • 指定导入模块时使用 package.json 中的哪个字段,这里的配置将优先使用 browser 属性解析文件,其次是 module,最后是 main
  • symlink
  • 告诉 webpack 解析模块时应该搜索的目录,这里对应的就是 node_modules 目录
  • 解析 webpack loader 包,指定 node_modules 目录
  • 代码包是包含副作用的,不希望被 tree shaking 优化
  • 配置node环境,在构建过程中对 fs(文件系统模块)和 path(路径模块)的引用替换为一个空对象,从而在浏览器环境中模拟文件系统和路径操作,在浏览器环境中,一些 Node.js 特定的模块是不可用的,因此需要通过这种方式进行处理
  • 添加MultiPlatformPlugin 插件,支持跨平台文件

图片

自定义配置

查看 buildConf 的其余配置,这段代码主要负责初始化和配置一些构建过程中所需的插件、常量和选项,确保构建过程中能够根据配置进行适当的处理和优化

  • 如果是构建插件(isBuildPlugin 为真),就会处理复制文件的逻辑。如果存在 copy 对象,则将其现有的 patterns 属性提取出来,如果不存在,则创建一个空数组。随后,将插件相关的文件夹路径加入这个数组。最后,使用 Object.assign 将更新后的 patterns 放回到 copy 对象中。这样,如果之前已经有一些复制规则,现在就添加了插件相关的复制规则
  • 配置插件,将 copy 属性解析为 copy-webpack-plugin 插件,加入到 webpack 中
  • 设置环境变量
  • 预备构建过程中所需的常量和入口文件的配置。首先,通过 getRuntimeConstants(runtime) 获取运行时常量,其中可能包含运行时所需的配置或环境常量。接着,通过 mergeOption([processEnvOption(env), defineConstants, runtimeConstants]) 合并来自不同来源的常量选项,包括从环境变量提取的配置、预定义的常量以及之前获取的运行时常量。最后,通过 getEntry({ sourceDir, entry, isBuildPlugin }) 获取项目的入口文件配置,其中包括源代码目录、入口文件的配置以及构建是否为插件
  • 配置共享的代码块(Common Chunks)以用于构建。首先,根据是否构建插件来设置默认的共享代码块列表 defaultCommonChunks,其中包括了运行时、第三方库、Taro 框架和通用代码块。接着,通过一系列条件语句,允许用户自定义共享代码块的配置。如果 commonChunks 是一个函数,则调用它,将默认的共享代码块传递给它,允许用户根据需要修改或替换默认的配置。如果 commonChunks 是一个非空数组,则将其用作自定义的共享代码块配置。最后,通过调用 getDefinePlugin([constantsReplaceList]) 获取定义插件的配置,其中包括了前面整理好的常量替换列表。有利于灵活地配置和生成最终的共享代码块配置,以便在构建过程中进行优化
  • 判断是否开启了主包优化,如果开启了就配置相应的分割插件

图片

图片

图片

Taro 构建过程中 webpack 配置的核心部分,通过链式调用 webpack-chain 库的方法逐步配置了 webpack 的各项参数,包括模式、入口、出口、目标、解析规则、插件、优化等

  • mode:提供 mode 配置选项,告知 webpack 使用相应模式的内置优化。
  • devtool:控制是否生成 source-map。
  • entry:入口文件,也就是 app.js。
  • output:定义代码编译后的生产目录。
  • target:指定目标(target)环境。
  • resolve:合并 alias 别名选项。
  • module:配置 module,这里主要是配置一些不同的 loader。
  • plugin:配置 plugin 插件。
  • optimization:手动配置了一些编译选项优化。

图片

webpack 代码编译

webpack 的编译过程,支持 watch 模式,并提供了一些回调函数用于处理编译结果。

图片

(本文作者:刘健)

图片


哈啰技术
89 声望51 粉丝

哈啰官方技术号,不定期分享哈啰的相关技术产出。