本文是将 Taro 3.0.14 跨版本升级到 Taro 3.5.3 项目实战,基于 Vue 2.x 的框架,如果是 Vue 3 或 React 版本建议多参考官方文档相关说明。
背景
团队中微信小程序项目采用的是 Taro 框架,在 Taro 3 出来之后,就使用 Taro 3.0.14 版本进行实际项目开发。随着项目的不断迭代,发现一个问题,小程序的主包越来越大(从项目开始就采用了分包),直到有一天超过了2M,严重影响到了项目的正常迭代。在这以前,已经进行了一些常规的优化:如分离 moment.js 的语言包;通过微信小程序开发者工具自带的依赖包分析,再配合 webpack-bundle-analyzer 插件,对主包中引入比较大的业务代码做拆分、优化等等。
明明很多代码只在分包中引用,依然会引发主包的体积变大,原因是在开发小程序时, Taro 编译器依赖 SplitChunksPlugin 插件抽取公共文件,默认主包、分包依赖的 module 都会打包到根目录 vendors.js 文件中(有一个例外,当只有分包里面有且只有一个页面依赖 module 时,会打包到分包中依赖页面源码中),直接影响到小程序主包大小,很容易超出 2M 的限制大小。官方也在文档中给出了对应的解决方案,修改 SplitChunks 默认配置,但是注意的是将 Taro 升级到 3.3.11 及以上版本。
为了保证业务正常迭代,在做了一定的技术调研后,决定将现有的项目做一次 Taro 跨版本升级。本文是将项目从 Taro 3.0.14 升级到 Taro 3.5.3 的一次记录。
目录
- 版本差异梳理
- 升级需要调整的代码
- 升级前后对比
版本差异梳理
此部分整理了一些 Taro 大版本的更新说明,尤其是一些有破坏性的变更(breaking change)。如果不感兴趣,可以直接跳过此部分,进入
升级需要调整的代码
模块
下面整理了一些个人认为对升级框架可能有帮助的点,汇总如下:
版本号 | 更新说明-微信小程序 | 更新说明-H5 | 需要关注的 Breaking Change |
---|---|---|---|
3.5.2 | 优化主入口引用样式文件编译问题 | 新增支持 movable 组件 fix ;prebundle: 默认继承 webpack 配置,并支持开发者自定义拓展 | |
3.5.0 | 对小程序的内部实现进行优化,减少约 50k 包体积,同时降低内存占用,减少 setData 发送的数据量 | ||
3.4.14 | 优化 Swiper 组件的样式引入 | ||
3.4.12 | 优化智能提取分包依赖插件 | 修复 Swiper 组件随着 tab 页面切换,总是跳到最后一个元素开始轮播的问题 | |
3.4.11 | 修复 iOS 视频组件全屏事件导致的错误; 修复 iOS 视频组件层级问题; 修复 iOS 视频组件在沉浸式状态栏下,退出全屏时的定位问题; 修复 onProgressUpdate 方法错误返回值; 修复 tabbar 在配置特殊自定义路由情况下,从非首页进入应用情况下,图标显示错误问题 | ||
3.4.8 | 支持微信小程序 Input 组件的安全键盘属性 | ||
3.4.5 | 修复独立分包页面的 Page 构造器被重复调用,从而报页面重复注册异常的问题; 修复独立分包页面 base.wxml 依赖引用异常的问题; 修复小程序无法绑定 style 属性的问题; 抹平 Taro.getExtConfig API 在支付宝小程序与微信小程序的返回值差异; 修复 Vue 不能使用 module 模式的 CSS Module 的问题; 修复公共样式不能覆盖全局样式的问题 | 修复 Vue3 使用 ref 引用时未引用原生组件实例的问题; Vue3 支持在 JSX 中使用 Taro 组件; 修复设置 basename 后不跳转默认路由的问题; 修复 Textarea 设置了 min-height 在 caculateContentHeight 时会陷入死循环奔溃的问题; Taro.request 请求增加 response 判断 | |
3.4.3 | 支持微信小程序 Button 组件的 open-type 属性以获取头像昵称 | ||
3.4.0 | 运行时体积优化,相比 Taro v3.3 版本大约减少了 30k 空间 | ||
3.3.20 | 优化 MiniSplitChunksPlugin 的运行性能 | ||
3.3.13 | 确保 onShow 在 onLoad 之后再执行 | ||
3.3.9 | 修复 H5 模式打包页面后在安卓低端机上白屏报错的问题 | ||
3.3.4 | 补全微信小程序的 exitMiniProgram API; 修复 optimizeMainPackage 配置在打包原生小程序页面时无法生效的问题; 修复 Vue 2/3 不能正确使用端平台插件的问题; 修复多次调用 innerHTML 时旧节点没有正确卸载的问题; 修复 Vue3.2+ 版本静态节点渲染报错的问题; 修复使用 Vue v-for 指令时百度小程序 swiper 组件显示空白页的问题; | ||
3.3.3 | 修复 innerHTML API 对 <style> 标签的解析问题;修复开发微信小程序插件时编译报错的问题; 修复微信小程序插件中调用 Taro 的 APIs 时报错的问题; | 修复使用 Vue 开发时,picker 组件的 rangeKey 属性为 undefined 的问题; 修复 Taro.setClipboardData API 在写入复制内容的时候对换行符解析失效的问题; 修复设置 router.basename 失效的问题; 修复频繁跳转时会导致多页面共存的问题; | |
3.3.2 | 优化分包提取插件; 修复开发者工具因找不到 sub-common 下的文件而导致报错的问题; 修复分享朋友圈后再进入页面,显示白屏的问题; 修复 catchMove 设置 false 时失败的问题; 修复 catchMove 不能动态切换的问题; 优化对 comment 节点的处理; 修复 Textarea 组件的 showConfirmBar 属性失效的问题; 为微信小程序插件增加 enablekeyboardAccessory 参数,用于支持使用 组件; | 修复 onShow 时调用 getCurrentPages 获取不到当前页面实例的问题; 修复设置 router.basename 失效的问题; 修复 Swiper 组件的性能问题; 降级 resolve-url-loader 到 3.x 版本,修复编译时出现的 a valid source-map is not present 报错; | 与 sub-common 有关 |
3.3.0 | 支持使用 H5 标签编写 Taro 应用; 修复使用 Vue2 时会生成多余文本节点 "" 的问题; 修复 insertAdjacentHTML API 在 afterbegin 时的错误 | ||
3.2.9 | 体积优化,添加小程序提取公共模块插件,自动分析抽离分包时子包的公共依赖并打包到子包中 | ||
3.1.0 | 组件 View 增加 catchMove 属性,解决滚动穿透问题。 | 用户编写的入口组件需要修改如下: // app.js // 3.0 const App = new Vue({}) // 3.1 const App = {} |
升级需要调整的代码
本文仅记录和框架相关的代码调整,业务相关的代码已过滤。
基础代码调整
- node 版本升级,需要使用 node 12+ 的版本,node 10 的版本打包会有问题
- 修改 package.json 中 3.0.14 的版本号,都改为 3.5.3
- 删除 package-lock.json 文件
- 删除 node_modules 文件
- 修改 app.js,const App = new Vue({}) 改为 const App = {}
- 需要安装 :@tarojs/plugin-framework-vue2@3.5.3
- 需要安装:"@vue/babel-preset-jsx": "^1.2.4"
- sass 不要升级,保证版本:"sass": "1.38.0" (注意,此处与实际项目相关,可不做修改)
- "mini-css-extract-plugin": "0.8.0"(注意,此处与实际项目相关,可不做修改)
- 如果使用了 moment.js 库,需要注意,在 config/index.js 文件中:
- 调整 IgnorePlugin 参数,去掉 moment 后面的 $
// 调整前 webpackChain(chain, webpack) { chain .plugin("IgnorePlugin") .use(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)); }, // 调整后 webpackChain(chain, webpack) { chain .plugin("IgnorePlugin") .use(new webpack.IgnorePlugin(/^\.\/locale$/, /moment/)); }, // 此处与 Taro 依赖的 webpack 版本升级有关,具体未细究,感兴趣的同学可以去做深一步研究
- 用于排除 moment 中的其他语言包,减少主包体积
- 如果有特殊语言包要求,建议根据实际项目调整
- config/index.js,添加 optimizeMainPackage 配置项,参考 Taro 官网
- config/index.js,修改 deviceRatio 中 375:1/2 为 375:2/1,如果是其他比例则可以不用调整
- scr/app.js 中,如果引入了 lodash,则需要做如下调整:
// 为了解决 Taro 在处理 lodash 库报错的问题,参考 https://github.com/NervJS/taro/issues/8098 Object.assign(global, { Array: Array, Date: Date, Error: Error, Function: Function, Math: Math, Object: Object, RegExp: RegExp, String: String, TypeError: TypeError, setTimeout: setTimeout, clearTimeout: clearTimeout, setInterval: setInterval, clearInterval: clearInterval })
微信小程序项目相关的代码调整
- 多层级嵌套 template 之后,用 if 条件语句判断是否显示会有问题,需要用 v-show 或 v-else-if 做对应的逻辑处理,具体原因未知。即遇到下图所示的报错时,可以考虑从此处下手解决
H5 项目相关的代码调整
- config/index.js ,调整 router 设置:
//H5 配置调整,路由 router: { mode: 'browser', basename: '/h5/', }, // 改为 router: { mode: 'browser', basename: '/h5', }, //原因:https://github.com/NervJS/taro/issues/10247
- 给容器添加 id,原因是 Taro 3.5.3 之后,H5 中的 DOM 结构有变化,原来默认的 container 元素,现在没有了
- src/index.html ,因为 Taro 3.5.3 之后不再默认以 640 为设计稿版本,需要做对应调整,参考 github.com/NervJS/taro… ,将3.5.3的项目初始化的 index.html 对应部分复制过来
<title></title> <script><%= htmlWebpackPlugin.options.script %></script>
- 移除 .taro_page 类名相关的处理逻辑,因为新版本的 Taro 做了 dom 结构和类名的改造,如果有依赖此类名的逻辑,需要调整
升级前后对比
其实主要是用数据来说明升级的意义。
- 代码依赖分析对比 - Taro 3.0.14 版本
- 代码依赖分析对比 - Taro 3.5.3 版本
-
代码依赖分析对比 - 总结
- 通过图中可以看出主包的体积由 1.86M 降到了 1.45M
- 升级后的分包体积都变大了,因为都增加了一个 sub-common 的目录,具体说明官网中有描述
- 随着后续分包不断增加内容,除非主包中也有引用,否则不会太影响主包的大小,符合预期
-
package.json 版本依赖对比
- Taro 3.0.14 版本
"dependencies": { "@babel/runtime": "^7.7.7", "@tarojs/components": "3.0.14", "@tarojs/extend": "^3.0.14", "@tarojs/runtime": "3.0.14", "@tarojs/taro": "3.0.14", "animate.css": "^4.1.1", "fundebug-javascript": "^2.8.0", "fundebug-wxjs": "^1.4.1", "html2canvas": "1.0.0-rc.4", "lodash": "^4.17.20", "md5": "^2.3.0", "moment": "^2.29.1", "qs": "^6.9.4", "v-viewer": "^1.6.3", "vue": "^2.5.0", "vue-template-compiler": "^2.5.0", "vue-touch": "^2.0.0-beta.4", "vuex": "^3.5.1" }, "devDependencies": { "@babel/core": "^7.8.0", "@tarojs/cli": "3.0.14", "@tarojs/mini-runner": "3.0.14", "@tarojs/plugin-vue-devtools": "^3.3.7", "@tarojs/webpack-runner": "3.0.14", "@types/webpack-env": "^1.13.6", "babel-plugin-import": "^1.13.3", "babel-preset-taro": "3.0.14", "cross-env": "^7.0.3", "eslint": "^6.8.0", "eslint-config-prettier": "^6.15.0", "eslint-config-taro": "3.0.14", "eslint-plugin-vue": "^6.x", "miniprogram-ci": "^1.4.13", "prettier": "^2.2.0", "stylelint": "9.3.0", "vconsole": "^3.3.4", "vconsole-webpack-plugin": "^1.5.2", "vue-lazyload": "^1.3.3", "vue-loader": "^15.9.2", "webpack-bundle-analyzer": "^4.5.0" }
- Taro 3.5.3 版本
"dependencies": { "@babel/runtime": "^7.7.7", "@tarojs/components": "3.5.3", "@tarojs/extend": "3.5.3", "@tarojs/runtime": "3.5.3", "@tarojs/taro": "3.5.3", "@tarojs/taro-h5": "3.5.3", "@tarojs/plugin-framework-vue2": "3.5.3", "animate.css": "^4.1.1", "fundebug-javascript": "^2.8.0", "fundebug-wxjs": "^1.4.1", "html2canvas": "1.0.0-rc.4", "lodash": "^4.17.20", "md5": "^2.3.0", "moment": "^2.29.1", "qs": "6.9.6", "v-viewer": "^1.6.3", "vue": "2.6.14", "vue-template-compiler": "2.6.14", "vue-touch": "^2.0.0-beta.4", "vuex": "^3.5.1" }, "devDependencies": { "@babel/core": "^7.8.0", "@tarojs/cli": "3.5.3", "@tarojs/mini-runner": "3.5.3", "@tarojs/plugin-vue-devtools": "3.5.3", "@tarojs/webpack-runner": "3.5.3", "@types/webpack-env": "^1.13.6", "@vue/babel-preset-jsx": "^1.2.4", "babel-plugin-import": "^1.13.3", "babel-preset-taro": "3.5.3", "cross-env": "^7.0.3", "eslint": "^6.8.0", "eslint-config-prettier": "^6.15.0", "eslint-config-taro": "3.5.3", "eslint-plugin-vue": "^6.x", "miniprogram-ci": "^1.4.13", "prettier": "^2.2.0", "stylelint": "9.3.0", "vconsole": "^3.3.4", "vconsole-webpack-plugin": "^1.5.2", "vue-lazyload": "^1.3.3", "vue-loader": "^15.9.2", "webpack-bundle-analyzer": "^4.5.0" }
- 总结:对比 package.json 中的依赖可知,升级后的版本依赖,只需要将原有的 3.0.14 直接替换成 3.5.3 即可
杂谈
- 本次升级,是一个实战案例,非 Demo 项目,因此比较具有借鉴意义,整个升级的流程可以分为以下几点:
- 发现问题:主包逐步变大,如何优化
- 定位问题:通过详细阅读 Taro 官方文档,以及在 Taro 的 Gtihub 中其他同学提出的 issues 中查找关键词,定位具体的原因
- 制定技术方案:
- 通过对比 Taro demo 文件,模拟项目的多包引入,分别打包 3.0.14 以及 3.5.3 版本的代码,对比打包后的代码体积
- 拷贝现有项目,升级框架,分别打包 3.0.14 、3.5.3 版本,此步骤仅考虑可以正常打包,暂不考虑代码逻辑正确性,对比打包后的代码体积
- 确定技术方案可行性
- 制定升级的计划:
- 基于确定后技术方案,在原项目中创建新分支,进行版本升级
- 本地运行,主流程自测,包括小程序、H5
- 本地编译,真机预览,主流程自测,包括小程序、H5
- 整理自测过程中的代码改动,梳理业务影响范围,便于 QA 同学制定测试方案(重点有影响的业务模块)
- 自测通过后提测
- QA测试通过后上线
- 至此,完整的升级 Taro 框架流程结束
- 注意事项:
- 不要过分依赖官方文档的配置项,并不是简单改改配置就可以万无一失,一定要经过严谨的测试。因为每个团队编写代码的风格和质量都不尽相同,每个人遇到的问题也不尽相同
- 在做任何技术升级时,除非没有更优的解决方案,能通过技术手段解决的问题,尽量不要优先考虑改动业务。这是技术的价值的体现,也是基于投入产出比的考量。
- 在升级的过程中还遇到了 webpack 升级产生的问题,说明框架升级,不能仅关注框架本身,因为其依赖的三方类库可能也会影响你的代码。
- 特别感谢:感谢小伙伴 webgzh907247189(juejin.cn/user/400187…)帮忙定位 webpack 升级之后依赖的 IgnorePlugin 插件的差异,否则不能正常过滤 moment.js 的语言包
持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情
参考资料
- Taro-Github-Issues-mini-split-chunks :github.com/NervJS/taro…
- Taro 官方文档:taro-docs.jd.com/taro/docs/
浏览知识共享许可协议
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。