Taro+Vue3编译多端小程序的一些记录

avatar

前言

我们的项目历史是通过小程序为壳,内嵌H5的方式来满足多端小程序的业务诉求。但随着业务体量的上升,用户体验的追求和原生能力的需求不断增强,原来的“H5打天下”的方式已经逐渐落后,所以今年我们也启动了原生化工作,针对核心链路进行升级。

技术选型上,既然存在多端的场景,Taro会是当下相对最优的解决方案。不管是能力、文档,还是后续的维护上,都是极好的选择。

团队内部最大的分歧是在于JS框架的选择上,React还是Vue?React明显更适配Taro生态,但我们最终还是选择Vue3。原因从三点考量:1、我们的H5项目是使用Vue3维护,团队内部的基建基本是围绕Vue展开;2、跟第一点强相关,团队内部大部分同学对Vue3的熟悉度明显优于React,不是React学不会,但需要时间成本;3、Taro3针对Vue进行适配,基本能力上基本磨平了与React的差异,这样开发的成本会大幅下降。

当然,最终选择这样的方案是因为我们进行了一次尝试。业务在某次需求评审上提出了抖音小程序的诉求,我们使用Taro3+Vue3的方案进行一个简易版本的小程序构建,发现使用Vue3进行代码迁移适配的工作量远远低于预期,大部分业务代码都可以直接复用,很大一部分工作量在于小程序生命周期的适配、样式兼容、UI组件切换等。

主要技术栈

  • Taro3
  • Vue3
  • TypeScript
  • Pinia
  • NutUI(后续替换为自建UI组件库)

编译支付宝、微信、抖音、mPaas小程序

项目搭建

Taro项目的基础初始化,NutUI配置等这里就不详细赘述了,详情可见官网。这里记录一些细节或注意事项。

包体积

小程序有主包2M的体积限制,当业务代码过重,体积超限问题就会持续困扰我们。

可以build后直接在IDE上看到各个包的体积。

1. mini.optimizeMainPackage

Taro提供了这个配置,可以将非主包引用的代码打包至子包

2. webpack配置里可以使用terser等插件

3. 检查引用

比如有个三方库的功能实际只在子包使用,但因为库里部分枚举值等静态配置在全局config文件里引用了,而这个文件又在主包使用,导致整个库被打入主包。

我们可以将这部分静态配置直接迁移到项目中,不通过import的方式引用,也可以将这个配置单独为一个文件,避免整个文件在主包重复引用。

4. 自定义组件

开发者可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用;也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护。自定义组件在使用时与基础组件非常相似,但自定义组件会单独打包。

使用方式:

在对应页面的config文件内引用自定义组件,在对应页面正常使用即可。

{
  usingComponents: {
    'debug-tool': '../../scopeComponent/DebugTool/index',
  },
}
<debug-tool />

PS:自定义组件拿不到id,也不能用ref调用,建议使用事件进行交互;

5. 静态资源使用CDN

6. NutUI样式文件

NutUI库的样式文件特别大,而使用时需要在app.tsx内直接引用。可以考虑把这个文件放到本地,仅保留需要用到的样式属性。

项目&页面配置

1. 按需引用

通常情况下,在小程序启动时,启动页面依赖的所有代码包(主包、分包、插件包、扩展库等)的所有 JS 代码会全部合并注入,包括其他未访问的页面以及未用到自定义组件,同时所有页面和自定义组件的 JS 代码会被立刻执行。这造成很多没有使用的代码在小程序运行环境中注入执行,影响注入耗时和内存占用。

小程序支持通过配置,有选择地注入必要的代码,以降低小程序的启动时间和运行时内存。

lazyCodeLoading: 'requiredComponents'

PS:使用webview时会使用createWebViewContext来创建web-view 上下文,在支付宝端直接配置lazyCodeLoading: 'requiredComponents',会导致postMessage异常,需要提前在app里执行相关初始化逻辑。

2. 沉浸式navigationBar

小程序支持沉浸式navigationBar,可以使用以下配置

{
  navigationStyle: 'custom',
  enableShareAppMessage: true,
  navigationBarTitleText: ' ',
  transparentTitle: 'always',
  titlePenetrate: 'YES',
}

3. 微信自定义组件样式问题和使用问题

默认情况下,自定义组件的样式只受到自定义组件 wxss 的影响。

  • isolated 表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响(一般情况下的默认值);
  • apply-shared 表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面;
  • shared 表示页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响页面和其他设置了 apply-sharedshared 的自定义组件。(这个选项在插件中不可用。)
styleIsolation: 'shared'

4. 分包配置

{
  pages: ['pages/index/index'],
  subPackages: [
    {
      root: 'subPages/A',
      pages: ['index']
    }
  ],
  preloadRule: { // 分包预加载配置
    'pages/index/index': {
      network: 'all',
      packages: ['subPages/A'],
    },
  },
}

5. 小程序项目配置文件

每端都需单独配置

安装 Pinia 进行状态管理

yarn add pinia
yarn add taro-plugin-pinia

项目配置文件 config/index.js 中配置:

// ...
plugins: ['taro-plugin-pinia'],
// ...

使用pinia,建议不同模块的store,json放入指定分包,不要把主包没有用到的模块放进去,影响主包体积。

子组件onShow

只有在页面组件才会触发 onShow 生命周期。子组件可以使用 Taro 内置的消息机制监听页面组件的 onShow() 生命周期来模拟子组件的onShow

eventCenter.on(getCurrentInstance().router.onShow, () => {
  console.log('onShow')
})

总结

上述记录了一些项目搭建和开发时遇到的一些坑或思考,感谢阅读~