什么是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 模式,并提供了一些回调函数用于处理编译结果。
The End
如果你觉得这篇内容对你挺有启发,请你轻轻点下小手指,帮我两个小忙呗:
1、点亮「在看」,让更多的人看到这篇满满干货的内容;
2、关注公众号「哈啰技术」,可第一时间收到最新技术推文。
如果喜欢就点个👍喔,有您的喜欢⛽,我们会更有动力输出有价值的技术分享滴。