摘要
文章对搭建业务和源码业务的性能差异进行分析,指出搭建业务性能差的原因,阐述搭建业务性能优化方案,包括服务端文件加载优化、seed 缓存、搭建构建源码等,也提到优化方案存在的权衡之处。
一、业务类型与性能差异
搭建业务和源码业务是淘内页面常见的两种类型。从终端平台 - 搭建研发团队的视角看,这两者更多是基于业务灵活运营和开发维护成本的考量。在已知搭建页面性能较差,源码页面性能更好的情况下,加入“性能”维度后,形成了性能优化的“不可能三角”。对于源码业务,运营成本低,性能优化较容易;而搭建业务由于其体系架构,性能优化相对困难。
二、搭建业务性能差的原因
1. 模块搭建的问题
搭建体系依赖 feloader(模块加载器) + seed(依赖、版本声明文件),与源码相比,存在一些性能劣势。它输出的主文档体积大,且服务端会有拉取文件、seed 依赖计算等耗时操作。
三、性能优化方案
1. 服务端文件加载优化
经过打点日志分析,发现随着并行处理资源数量增加会有时间片抢占,导致单个任务 resolve 时间过长。通过将多个文件合并成一个单文件的实验,渲染耗时显著降低约 60%,为后续优化奠定基础。
// 这里可推测是 JavaScript 代码,但原文未给出具体代码内容示例,仅描述操作结果
2. Seed 缓存
在服务端文件加载优化减少运行时任务数量后,单个任务仍存在 seed 计算耗时。于是重新审查代码进行优化,并且在服务端文件加载优化的基础上开启 seed 缓存。
3. 搭建构建源码
搭建业务存在运行时动态拉取模块、计算依赖等操作,相比源码项目有性能劣势。所以推出搭建构建源码(AOT 构建)方案,即提前收集页面搭建模块然后生成源码项目进行构建。
模块规范
feloader 是基于 CMD 规范的模块加载器,而 web 开发中以 ESM 为主。两者在模块定义、加载、解析、依赖管理、执行顺序、导出和导入模块以及浏览器支持情况等方面存在差异。
// 例如模块定义对比
// CMD: 使用 define()函数定义模块
// ESM: 使用 export 导出模块
模块适配
回归到源码方案中,按照标准的 npm 依赖管理进行适配。搭建平台可从页面获取模块的npm 包名
和版本号,将其生成到 package.json。以特定依赖为例,会将其编译成特定的数据结构以保证功能正常运行。
// 如依赖编译示例代码
import * as Mod0Instance from '@ali/foo';
const { default: defaultExport0,...nameExports0 } = Mod0Instance;
import * as Mod1Instance from '@ali/bar';
const { default: defaultExport1,...nameExports1 } = Mod1Instance;
export default {
'@ali/foo': {
defaultExport: defaultExport0,
nameExports: nameExports0,
},
'@ali/bar': {
defaultExport: defaultExport1,
nameExports: nameExports1,
},
};
调试
将搭建页改造成“源码页”后,模块代理规则失效,模块调试变成源码项目调试。考虑借助 OSS 或 git 托管平台解决调试问题,最终通过绑定公共账号将代码推送到 git 平台,以时间戳作为分支名,开发者可根据构建日志快速 clone 对应仓库并进行调试。
四、优化方案的权衡之处
通过 AOT Build + 模版的方式提升了服务端渲染性能,但存在 trade - off,如每次发布前要等待构建完成,以确保最终预览是最新代码内容。