当前位置: 首页 > news >正文

搭建业务的性能优化指南

8d6063515d1397516831b918c233b1dc.gif

这是一篇搭建业务优化的心路历程,也是写给搭建业务的性能优化指南。

63de7cb107e36c403205762fa1ef5b13.png

前言

直到今天,淘内的页面大多都迁移到了 SSR,从我们终端平台 - 搭建研发团队的视角看,业务大致可以分为两类 —— 搭建派 和 源码派。

这两者互不冲突,更多是基于业务灵活运营和开发维护成本的考量,大致遵循以下原则:

f73a594ebd767213f3da657f368bcb10.jpeg

而且已知搭建页面性能较差,源码页面性能更好的情况下,我们又加入了“性能”这个维度,构成了一个性能优化的“不可能三角”,即:

  • 对于采用源码开发的业务,自然不存在什么运营成本,性能优化起来就比较顺手;

  • 对于采用模块搭建的业务,由于搭建体系天然不是性能最优的架构,性能优化就相对没那么自然。

f91da47e47ec6de205226ce371868942.jpeg

笔者作为【搭建派】solution 的开发者,从一开始就注定要肩负着媲美源码派性能的重任。

下面来说说搭建派是如何打破这个不可能三角的,请收好你的搭建优化指南!

搭建优化指南

要想解决搭建的性能问题,我们就要先了解搭建慢在哪里?

  模块搭建慢在哪里?

搭建体系依赖 feloader(模块加载器) + seed(依赖、版本声明文件),相比源码,不仅输出的主文档体积会大,而且服务端会有拉取文件、seed依赖计算等耗时。

015207fbdcdd4c1bd83260bc519ecd55.jpeg

服务端文件加载优化

经过一系列打点日志分析后发现,虽然我们已经尽可能并行处理运行时任务,但随着并行处理的资源数量增加,存在时间片抢占,导致单个任务 resolve 时间过长。

为了验证这个猜想,于是我们从扩展入手,将多个文件合并成一个单文件,果然渲染耗时显著降低约 60%,这也为我们后续其他优化打下了基础。

01f10265280fb189055b6b645630a4fd.png

Seed缓存

服务端文件加载优化减少了运行时处理任务的数量,但是即使是单个任务也存在 seed 计算的耗时, 于是我们开始了针对 seed 部分的改造处理,重新 review 了代码进行了优化,并且在有了服务端文件加载优化的基础下,开启seed 缓存变为了可能。

无论是服务端文件加载优化还是 seed 缓存,这二者都是针对运行时做的优化,但是模块加载还是存在多个并行任务,相比于扩展的低复杂度以及单仓库,将模块打包成单文件不太现实,保持现状似乎就是最终的方案了?

但是毕竟还是存在一部分开销,而且每次主文档返回我们都要输出一大坨 seed 信息来让 hydrate 正常工作,始终达不到源码的效果。模块维度的运行时优化似乎没有什么改造空间了,那能不能干掉以 feloader + seed 的动态加载逻辑?Why Not!我们接着往下看。

53d05f4f561080b8d17c89a3f79690ce.png

搭建构建源码

搭建业务由于存在运行时动态拉取模块、计算依赖等操作,相比于源码项目存在着天然的性能劣势。

有句话说的好:打不过就加入!

好汉不吃眼前亏,外表上看虽然是搭建,但其实我也可以是源码。

24a4ab6dfb2f4f5242fe057067297310.png

于是为了帮助搭建业务更好的完成性能指标,我们推出了 搭建构建源码 这个方案,也就是 AOT (Ahead Of Time) 构建,简单说就是提前收集页面搭建模块然后生成源码项目进行构建。

  模块规范

说起搭建就离不开 feloader + seed 体系,这里就不再过多介绍,ATA 也有很多相关文章介绍,感兴趣可以自行搜素阅读。

社区开发中,主流的模块规范是 commonjs(CJS) 和 esmodule(ESM),也有诸如 AMD、CMD 等规范,feloader 是基于 CMD 规范的模块加载器, web 开发中我们以 ESM 为主,去掉 feloader 可以约等于从 CMD 迁移到 ESM,它们之前的映射关系大致如下:

步骤

CMD

ESM

定义模块

使用 define() 函数定义模块

使用 export 导出模块

加载模块

使用 require() 函数加载模块

使用 import 导入模块

模块解析

使用模块加载器解析依赖关系并加载模块

使用 JavaScript 引擎内置的模块解析机制

依赖管理

通过定义依赖列表(Seed)来管理模块依赖

通过模块引入语句来管理模块依赖

模块执行顺序

异步加载模块,按照依赖顺序执行

同步加载模块,按照调用顺序执行

导出模块

使用返回值或导出对象来导出模块

使用 export 关键字导出模块

导入模块

使用回调函数参数或全局变量来导入模块

使用 import 关键字导入模块

浏览器支持情况

需要使用 CMD 模块加载器支持

部分现代浏览器原生支持 ES 模块

搞清楚各个环节做了什么事情之后,我们的适配工作就逐渐清晰。

  模块适配

回归到源码的方案中,我们只需要按照标准的 npm 依赖管理进行适配即可。

搭建平台可以很容易从页面获取到所有模块的 npm 包名 和 版本号,有了这两个信息,在脚手架直接生成到package.json即可,另外模块的版本号根据搭建页面是正式还是测试页进行了区分,当在测试页调试的时候,会通过 semver 取到 beta 版本,确保依赖正确

以下述依赖为例:

{"@ali/foo":">4.1.0-beta <4.1.0""@ali/bar":">4.1.0-beta <4.1.0"
}

脚手架会将其编译为如下文件,也就是 solution 内部消费的模块的数据结构,在最小改动的前提下保证功能的正常运行:

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,},
};

当然适配工作远没有这么简单,其他的就不在此过多展开。

技术层面的适配基本完成后,然后就是产品上的功能的实现,整个流程图如下:

8eb4320e30e1a9b3631d827f93ce3145.jpeg

  调试

由于我们将搭建页改造成了“源码页”,模块代理规则不再有效,也就是本地的单模块是无法用于代理调试的即 模块调试转变成了源码项目调试

但真实的源码项目又在云端生成,所以调试问题就转化成了——如何保存源码项目,并支持开发者下载获取指定版本。

  • 设计

一开始想到借助 OSS,通过在构建器中压缩源代码然后调接口上传,后来想到项目上传不就是 git 托管平台所做的事情吗,所以问题又变成了如何把代码上传到 git 平台。

由于是云构建,机器不固定,好在我们的代码托管平台提供了通过域账号和 privateToken登录的方式,这样只需绑定一个公共账号即可将代码推送上去。

同时我们将时间戳(YYYY-MM-DD-mm)作为对应的分支名,现在开启构建后,开发者通过构建日志即可快速 clone 对应分值仓库,然后通过我们预设好的代理规则即可进行快速调试!

dd6f180b536233961f31da0f85b59188.png

结语

通过 AOT Build + 模版的方式来实时生成源码项目,避免运行时动态获取模块的耗时,有效提升了服务端渲染的性能。当然也存在trade-off,如

  • 每次发布前都要等待构建完成,以确保最终预览的是最新的代码内容

相信经过后期的不断使用,会将整个链路打磨的更加贴合用户体验!

团队介绍

我们是淘天集团—终端平台团队,专注打造业界领先的终端技术以及丝滑流畅的体验,通过持续的创新突破,赋能前台业务、连接数亿用户,提供极致高可靠的服务、极致高性能的架构和极致高效率的产品。

¤ 拓展阅读 ¤

3DXR技术 | 终端技术 | 音视频技术

服务端技术 | 技术质量 | 数据算法

相关文章:

搭建业务的性能优化指南

这是一篇搭建业务优化的心路历程&#xff0c;也是写给搭建业务的性能优化指南。 前言 直到今天&#xff0c;淘内的页面大多都迁移到了 SSR&#xff0c;从我们终端平台 - 搭建研发团队的视角看&#xff0c;业务大致可以分为两类 —— 搭建派 和 源码派。 这两者互不冲突&#xf…...

电脑提示报错“Directx error”怎么解决?是什么原因导致的?游戏软件提示“Directx error”错误的解决方案

DirectX Error&#xff08;DX错误&#xff09;通常指的是在使用基于DirectX技术的应用程序&#xff08;尤其是游戏&#xff09;时遇到的问题。这个问题可能由多种因素导致&#xff0c;以下是一些可能的原因及相应的解决方案&#xff1a; 可能的原因 DirectX版本不匹配&#x…...

Linux——自定义简单shell

shell 自定义shell目标普通命令和内建命令&#xff08;补充&#xff09; shell实现实现原理实现代码 自定义shell 目标 能处理普通命令能处理内建命令要能帮助我们理解内建命令/本地变量/环境变量这些概念理解shell的运行 普通命令和内建命令&#xff08;补充&#xff09; …...

基于matlab程序实现人脸识别

1.人脸识别流程 1.1.1基本原理 基于YCbCr颜色空间的肤色模型进行肤色分割。在YCbCr色彩空间内对肤色进行了建模发现&#xff0c;肤色聚类区域在Cb—Cr子平面上的投影将缩减&#xff0c;与中心区域显著不同。采用这种方法的图像分割已经能够较为精确的将人脸和非人脸分割开来。…...

Unity跨平台基本原理

Unity跨平台基本原理 Unity跨平台基本原理微软的.Net是什么微软做 .Net平台的目的如何实现的.Net跨语言&#xff1f;总结 .Net Framework.Net Framework的体系结构CLR总结 如何实现的跨平台&#xff1f;.Net Core.Net FrameWork 到 .Net CoreMonoMono如何实现跨平台总结如何实现…...

【前端开发】小程序无感登录验证

概述 封装的网络请求库&#xff0c;主要用于处理 API 请求并支持自动处理 token 过期 和 token 刷新&#xff0c;适用于需要身份验证的应用场景&#xff0c;特别是在移动端中。 主要功能 自动附加 Token 在每个请求中自动附加 Authorization 头部&#xff0c;使用存储的 acces…...

Flink常见面试题

1、Flink 的四大特征&#xff08;基石&#xff09; 2、Flink 中都有哪些 Source&#xff0c;哪些 Sink&#xff0c;哪些算子&#xff08;方法&#xff09; 预定义Source 基于本地集合的source&#xff08;Collection-based-source&#xff09; 基于文件的source&#xff08;…...

spark同步mysql数据到sqlserver

使用Apache Spark将数据从MySQL同步到SQL Server是一个常见的ETL&#xff08;Extract, Transform, Load&#xff09;任务。这里提供一个基本的步骤指南&#xff0c;以及一些代码示例来帮助你完成这项工作。 ### 前提条件 1. **安装Spark**&#xff1a;确保你的环境中已经安装了…...

Python Web 开发:FastAPI 基本概念与应用

Python Web 开发&#xff1a;FastAPI 基本概念与应用 目录 ✨ 1. FastAPI 路由&#xff08;定义请求路径&#xff09;&#x1f680; 2. HTTP 请求方法&#xff08;GET、POST、PUT、DELETE&#xff09;&#x1f511; 3. 参数类型&#xff08;路径参数、查询参数、请求体&#…...

Linux设置开启启动脚本

1.问题 每次启动虚拟机需要手动启动网络&#xff0c;不然没有enss33选项 需要启动 /mnt/hgfs/dft_shared/init_env/initaial_env.sh 文件 2.解决方案 2.1 修改/etc/rc.d/rc.local 文件 /etc/rc.d/rc.local 文件会在 Linux 系统各项服务都启动完毕之后再被运行。所以你想要…...

go并发设计模式runner模式

go并发设计模式runner模式 真正运行的程序不可能是单线程运行的&#xff0c;go语言中最值得骄傲的就是CSP模型了&#xff0c;可以说go语言是CSP模型的实现。 假设现在有一个程序需要实现&#xff0c;这个程序有以下要求&#xff1a; 程序可以在分配的时间内完成工作&#xff0…...

nn.RNN解析

以下是RNN的计算公式,t时刻的隐藏状态H(t)等于前一时刻隐藏状态H(t-1)乘以参数矩阵&#xff0c;再加t时刻的输入x(t)乘以参数矩阵&#xff0c;最后再通过激活函数&#xff0c;等到t时刻隐藏状态。 下图是输出input和初始化的隐藏状态&#xff0c;当参数batch_first True时候&…...

How to monitor Spring Boot apps with the AppDynamics Java Agent

本文介绍如何使用 AppDynamics Java 代理监视 Azure Spring Apps 中的 Spring Boot 应用程序。 使用 AppDynamics Java 代理可以&#xff1a; 监视应用程序使用环境变量配置 AppDynamics Java 代理 在 AppDynamics 仪表板中检查所有监视数据 How to monitor Spring Boot app…...

Linux学习笔记12 systemd的其他命令

前文已经介绍了systemd在系统初始化中起到的作用和服务的管理和配置。这里补充一下systemd的其他工具和系统进程的管理 前文 Linux学习笔记10 系统启动初始化&#xff0c;服务和进程管理&#xff08;上&#xff09;-CSDN博客 Linux学习笔记11 系统启动初始化&#xff0c;服务…...

NGO-CNN-BiGRU-Attention北方苍鹰算法优化卷积双向门控循环单元时间序列预测,含优化前后对比

NGO-CNN-BiGRU-Attention北方苍鹰算法优化卷积双向门控循环单元时间序列预测&#xff0c;含优化前后对比 目录 NGO-CNN-BiGRU-Attention北方苍鹰算法优化卷积双向门控循环单元时间序列预测&#xff0c;含优化前后对比预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介…...

【分布式】分布式缓存

一、什么是分布式缓存 分布式缓存是一种将缓存数据存储在多个节点上的缓存方案。它通过将数据分散存储在多个节点的内存中&#xff0c;以提高系统的读取性能、降低数据库压力和提高系统可扩展性。 二、分布式缓存的优点 优点明细提高性能&#xff1a;分布式缓存可以将数据缓…...

深度学习中的迁移学习:应用与实践

引言 在深度学习领域&#xff0c;迁移学习&#xff08;Transfer Learning&#xff09;是一个非常强大且日益流行的概念&#xff0c;它通过将从一个任务中学到的知识应用于另一个任务&#xff0c;能够显著加快模型训练速度并提高其泛化能力。迁移学习在许多实际应用中都得到了广…...

28.UE5实现对话系统

目录 1.对话结构的设计&#xff08;重点&#xff09; 2.NPC对话接口的实现 2.1创建类型为pawn的蓝图 2.2创建对话接口 3.对话组件的创建 4.对话的UI设计 4.1UI_对话内容 4.2UI_对话选项 4.3UI_对话选项框 5.对话组件的逻辑实现 通过组件蓝图&#xff0c;也就是下图中的…...

Redis中的分布式锁(步步为营)

分布式锁 概述 分布式锁指的是&#xff0c;所有服务中的所有线程都去获取同一把锁&#xff0c;但只有一个线程可以成功的获得锁&#xff0c;其他没有获得锁的线程必须全部等待&#xff0c;直到持有锁的线程释放锁。 分布式锁是可以跨越多个实例&#xff0c;多个进程的锁 分布…...

CentOS 7安装mysql+JDK+Tomcat完成流程

一.安装mysql 即使是新的linux服务器&#xff0c;也要先验证是否有mysql已经安装&#xff0c;如果有进行卸载原版本&#xff0c;一定要确认是否mysql已不再使用 原安装情况&#xff08;直接执行命令即可&#xff09; whereis mysql rpm -qa | grep -i mysql rpm -e perl-DBD-M…...

大型机场U型机坪推出等待点运行优化【附案例】

✨ 长期致力于机场、U型机坪区、推出等待点、运行程序优化、启发式算法研究工作&#xff0c;擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅如需沟通交流&#xff0c;点击《获取方式》 &#xff08;1&#xff09;单通道U型机坪推出等待点位优化…...

从HackRF到USRP B210:我的SDR设备升级之路与真实体验对比

从HackRF到USRP B210&#xff1a;我的SDR设备升级之路与真实体验对比 作为一个长期沉迷于软件定义无线电&#xff08;SDR&#xff09;技术的爱好者&#xff0c;设备的选择往往决定了探索的边界。从最初的HackRF One到如今的USRP B210&#xff0c;这段升级旅程不仅是对硬件性能的…...

Vex:VS Code向量数据库管理扩展,提升AI开发效率

1. 项目概述&#xff1a;Vex&#xff0c;一个为开发者设计的向量数据库管理利器如果你正在用 VS Code 开发 AI 应用&#xff0c;并且和向量数据库&#xff08;比如 Milvus 或 ChromaDB&#xff09;打交道&#xff0c;那你大概率经历过这样的场景&#xff1a;为了插入几条测试向…...

保姆级教程:彻底解决CondaHTTPError网络连接失败(附.condarc文件完整配置流程)

深度解析CondaHTTPError&#xff1a;从网络诊断到.condarc文件全配置指南 遇到CondaHTTPError: HTTP 000 CONNECTION FAILED错误时&#xff0c;很多开发者会感到束手无策。这个问题通常出现在国内网络环境下&#xff0c;尤其是公司内网、校园网或使用某些代理服务后。本文将带你…...

大模型API响应延迟飙升470%,却查不到根因?SITS2026可观测性四象限诊断法,今天就落地

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;SITS2026可观测性框架的起源与核心范式 SITS2026&#xff08;System Intelligence Telemetry Standard 2026&#xff09;并非凭空诞生&#xff0c;而是源于云原生系统在超大规模微服务编排、边缘-中心协…...

深度相机三剑客:TOF、双目与结构光的场景化选型指南

1. 深度相机技术入门&#xff1a;从原理到应用 第一次接触深度相机时&#xff0c;我被各种技术名词搞得晕头转向。TOF、双目、结构光听起来都很高大上&#xff0c;但到底有什么区别&#xff1f;经过多年项目实战&#xff0c;我发现这三种技术就像不同的"眼睛"&#…...

告别头像上传模糊!用Cropper.js打造完美头像裁剪上传功能(附完整前后端代码)

从零构建高精度头像裁剪系统&#xff1a;Cropper.js全栈实战指南 每次上传头像时&#xff0c;你是否遇到过这样的尴尬——精心选择的图片上传后变得模糊不清&#xff0c;或者被强制拉伸变形&#xff1f;这种糟糕的用户体验在社交平台、企业系统中尤为常见。本文将带你从零构建…...

中兴光猫工厂模式解锁终极指南:3步开启Telnet高级权限

中兴光猫工厂模式解锁终极指南&#xff1a;3步开启Telnet高级权限 【免费下载链接】zteOnu A tool that can open ZTE onu device factory mode 项目地址: https://gitcode.com/gh_mirrors/zt/zteOnu 中兴光猫工厂模式解锁工具zteOnu是一款专为网络爱好者和技术人员设计…...

CANN/asc-devkit asc_select矢量选择函数

asc_select 【免费下载链接】asc-devkit 本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言&#xff0c;原生支持C和C标准规范&#xff0c;主要由类库和语言扩展层构成&#xff0c;提供多层级API&#xff0c;满足多维场景算子开发诉求。 项目地址: https://gitcode.com…...

告别臃肿!用Debootstrap从零打造一个极简Debian系统(保姆级分区+配置指南)

告别臃肿&#xff01;用Debootstrap从零打造一个极简Debian系统&#xff08;保姆级分区配置指南&#xff09; 在资源有限的环境中&#xff0c;一个臃肿的操作系统往往会成为性能瓶颈。无论是老旧电脑、嵌入式设备还是轻量级服务器&#xff0c;系统冗余不仅占用宝贵的存储空间&a…...