|
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 端的调试器了
一切都在慢慢变好……
希望今年能够将小程序彻底升级完,明年开始接新的容器,接更多小程序 |
|