查看: 132|回复: 3

esbuild 上生产

[复制链接]

4

主题

6

帖子

14

积分

新手上路

Rank: 1

积分
14
发表于 2023-3-6 19:40:06 | 显示全部楼层 |阅读模式
halo 大家好,我是 132,我在公司中负责小程序的工具链,使用 esbuild 的部分主要是编译器,容我一一道来
旧架构
小程序编译器的旧架构中,是使用 babel 先对小程序文件进行 AST 转换,转换为 react 项目,然后使用 webpack 对 react 项目进行打包,最终生成 js 文件,交给容器
babel => AST => React => webpack => js在这个架构中,每个环节都很慢,除了 webpack 打包慢,babel 也慢,递归进行文件 IO 操作,也很慢……
所以最初尝试 esbuild 是因为它快
新架构
在新架构中,使用 esbuild 做控制流,所有的文件 IO 操作交给 esbuild,而 AST 转换的部分则做成 esbuild 的 plugin
这样一来,不仅解决了 webpack 慢,还解决了 IO 操作慢的问题
当然,babel 操作 AST 也是很慢的,这部分我们待会再说
经过这一波重构,构建速度从 50s 降到了 10s,大约提升了 5 倍性能
更重要的是,新架构的控制流更清晰了,以后有什么问题就找 esbuild 的 plugin 就好了
esbuild => plugin(swc) => js为了节省 IO 的性能,我还是维护了一个图结构,它的作用主要是用来记录信息做缓存
esbuild 天坑
不支持 split common chunk
简直是天坑了……甚至我老板说只要 esbuild 解决不了这个问题,就无法上生产
https://github.com/evanw/esbuild/issues/1581
这是我提的 issue,esbuild 做过一个鸡肋版本的 split chunk,只支持 esm,也就是必须得是 支持 native module 的浏览器才可以
小程序当然不可以,所以不得已,临时解决方案
export const splitChuckCjs = {
  name: 'split-chunk-cjs',
  setup(build) {
    build.onEnd(result => {
      return Promise.all(result.metafile.outputs.mao(async path =>{
        const source = await fs.promises.readFile(path)
        await swc.transform(source, {
          jsc:{
            syntax: 'ecmascript',
            jsx: false,
            target: 'es5',
          },
          module: {
            type: 'commonjs'
          }
        })
      }))
    })
  },
}
就是先使用 esbuild build 出来 esm 的 chunks,然后再将产物使用 swc 转换为 cjs
在这里我顺便做了一层 es5 的兼容处理,因为上生成,还是有很多安卓 7- 的
至此,通过使用 esbuild + swc 配合的方式,可以说为生产做足了准备
使用 swc 做 AST 转换
小程序编译器最重要的一点就是将 wxml 转换为 jsx,这一步在旧架构中是使用 babel 做的,新架构中我使用 swc 做
swc 是 rust 写的,它的限制非常多,遍历起来很憋屈,为此我想了很多办法,具体可以看我之前写的一篇
最终它的完成度还是不够好,虽然我做了很多编译时检查,一些不支持的 case 可以在编译阶段友好地进行提示,但我感觉还是得继续写一段时间才行
这次我们上生产没有涉及这部分,先上 esbuild 再说,swc 下一波再升级
生产准备
携程小程序线上大约有 30+ 项目,在大公司,新技术想要上生产,只有两条路:
1. 领导帮忙推
2. 走群众路线很明显,我走的是群众路线……
我会把线上每一个小程序,都拉到本地,一个一个地跑,有问题就修改,然后给负责人提 pr
业务童鞋不需要排期,只需要审查一下我的 pr,然后测试发布即可
就这样,一个个来,终于苍天呐,不仅跑通了小程序,我还和业务童鞋们打成一片
但还不行……
我们上生产,指的是上 CICD,携程小程序有一套流畅地自动发布的链路,为了生产不出问题,我必须做好随时回退到旧版本的准备
具体是使用 npm alias 做到的,也就是同一个编译器,装俩版本
npm i miniapp-cli1@npm:miniapp-cli
npm i miniapp-cli2@npm:miniapp-cli@next然后只需要在 app.json 中配置一下版本,就可以走不同版本啦
总结
任重而道远,现在只是生产准备,可想而知年底不得消停
但我觉得一切值得……
另外今天得知一个好消息,有 native 小哥哥准备接坑小程序的 IOS 容器,我还是很开心的,很快就可以做 IOS 端的调试器了
一切都在慢慢变好……
希望今年能够将小程序彻底升级完,明年开始接新的容器,接更多小程序
回复

使用道具 举报

0

主题

1

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2023-3-6 19:40:42 | 显示全部楼层
基基tql
回复

使用道具 举报

2

主题

4

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2023-3-6 19:40:52 | 显示全部楼层
swc 和 esbuild 就剩下快了,功能缺挺多的。
回复

使用道具 举报

1

主题

3

帖子

4

积分

新手上路

Rank: 1

积分
4
发表于 2023-3-6 19:41:35 | 显示全部楼层
没有缺啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|多点娱乐

GMT+8, 2025-10-12 06:32 , Processed in 0.314688 second(s), 22 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表