当前位置: 首页 > 科技观察

爱彼迎将JavaScript代码打包工具从Webpack改用Metro,缩短了构建时间_0

时间:2023-03-19 15:24:18 科技观察

Airbnb将其JavaScript代码打包工具从Webpack改为Metro,减少了构建时间打包工具的痛苦。即使代码库翻了两番,Airbnb在2018年将其JavaScript代码捆绑工具从Webpack迁移到Metro后,也加速了前端的UX更改。在显着提高构建性能后,按交互时间衡量,UI更改速度提高了80%(TTI)公制。即使是最慢的生产级构建,编译49,000个模块(JavaScript文件)现在也快了55%,从使用Webpack时的30.5分钟增加到13.8分钟。对于那些使用Metro构建的页面,Airbnb自己的页面性能得分(PPS)也有所提高(约1%)。图1作为参考,在代码库在2018年左右翻了两番之后,简单的一行代码更改的平均页面刷新时间从30秒到2分钟不等,具体取决于项目规模。Airbnb的软件工程师RaeLiu在最近的这篇博文中介绍了Webpack和Metro的一些区别(一些迁移挑战的介绍。1.Metro简介Metro由Meta开发,是ReactNative的开源JavaScript代码打包工具,本文介绍的是Metro的定制版,因为Airbnb的架构不包含ReactNative,Airbnb的工程师除了与公司团队合作,还直接与Meta的Metro工程师合作,进一步开发这项技术。Metro打破打包按以下顺序分为三个步骤:解析、转换和序列化。解析:解析import/require语句。转换:转译代码(源到源编译器将现代Typescript/JavaScript源代码转换为JavaScript,并向后兼容旧版本浏览器),典型的工具是babel。序列化:将转换后的文件组合成bundle。期间在开发过程中,Airbnb工程师创建了一个带有自定义端点的Metro服务器系统,以处理构建依赖关系图和源映射、转换和捆绑JS和CSS文件。对于生产级构建,他们将Metro作为NodeAPI运行以处理解析、转换和序列化。迁移分两个阶段进行。最重要最好的是Metro开发服务器,因为缓慢的Webpack开发服务器是高开发生产力成本的来源。第二个迁移阶段致力于使Metro在功能上等同于Webpack,并在生产环境中在Metro和Webpack之间运行A/B测试。2、Metro和Webpack的两大区别按需处理JavaScript包Webpack在启动时预编译整个项目,而Metro只编译需要的内容。也就是说,一个JavaScript包严格来说是一个序列化的依赖图,入口点是图的根。在Airbnb,每个前端项目都有一个Node服务器来将路由匹配到特定的入口点。当请求网页时,DOM包含一个带有开发JavaScriptURL的脚本标记。Webpack在开始打包之前需要知道所有页面的所有入口点,而Metro只需要一个入口点并且可以根据请求处理JavaScript包。开发者对A页面进行了修改,但在下图中看不到:图2上图1a、1b中,浏览器加载A页面(1),向打包工具请求entryPageA.js文件(2)、packages工具用合适的包响应浏览器(4)。图1a和图1b的区别在于操作(3),因为Webpackgraph编译的是PagesB和C的入口点,而Metro不是这样,因为开发者在示例中只修改了PageA。Airbnb最大的前端项目之一有26,000个独特的模块,平均每页约7.2个模块。得益于服务器端渲染,Airbnb最终处理的模块数量翻了一番,达到约48,000个。在将Metro的按需编译模型付诸实践后,现在工作量减少了大约70%。多层缓存图2Airbnb利用Metro的多层缓存功能以及持久和非持久缓存。Metro允许工程师定义缓存实现,包括混合不同类型的缓存层,从而提供更大的缓存灵活性。Airbnb按优先级排列缓存层。如果在一个缓存层中没有找到结果,则将使用下一层,直到找到结果。在编译22,000个文件的项目中,与没有缓存的默认Metro实现相比,命中远程只读缓存导致服务器构建速度提高56%。第三个缓存层是远程只读缓存而不是读写缓存,因为写入远程缓存将是一个昂贵的网络调用,尤其是在慢速网络上。这个决定在开发中额外节省了17%的构建时间。Webpack有一个缓存层,但它与Metro提供的缓存层不同。3.BundleSplittingAirbnb博客文章中详述的技术挑战之一是BundleSplitting。这是跨动态导入边界拆分包的过程(也称为代码拆分)。开箱即用的Metro解决方案每个入口点生成大约5MiB的巨大数据包,这会增加浏览器资源和网络延迟,使HTTP缓存变得不可能。在上图中,import('./file')表示动态导入边界。左侧(3a)的数据包在右侧(3b)拆分为三个较小的数据包。执行import('./file')语句时会请求其他包。假设fileA.js已更改,需要重新下载整个包,以便浏览器获取fileA.js中的更改。如图3b所示,由于包被动态导入拆分,所以fileA.js的变化只会导致fileA.js包被重新下载。其余包可以重用浏览器缓存内容。在生产环境中,没有开发服务器,包是预先构建的。Airbnb的工程师从Webpack的包拆分算法中得到灵感,实现了类似的机制来拆分Metro依赖图。与动态导入边界的开发拆分相比,Airbnb上生成的包大小减少了大约20%(1226KB而不是1549KB)。开发包的优化方式不同,因为运行包拆分算法需要时间,工程师不想在开发拆分包大小上浪费时间。在开发情况下,页面加载性能优先于最小化包大小。Metro和Webpack具有可比较的包大小指标。标题:Airbnb从Webpack迁移到Metro,享受更短的构建时间,作者:JessicaWachtel