2024年Web前端最新如何将网站的性能提升十倍以上?(1),2024年最新前端面试知识点梳理

最后

好了,这就是整理的前端从入门到放弃的学习笔记,还有很多没有整理到,我也算是边学边去整理,后续还会慢慢完善,这些相信够你学一阵子了。

做程序员,做前端工程师,真的是一个学习就会有回报的职业,不看出身高低,不看学历强弱,只要你的技术达到应有的水准,就能够得到对应的回报。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

学习从来没有一蹴而就,都是持之以恒的,正所谓活到老学到老,真正懂得学习的人,才不会被这个时代的洪流所淘汰。

Elixir 采用 Actor 并发模型。每个“Actor”(即 Elixir 进程)的内存占用量都非常有限,仅为 1 到 2 KB。这意味着系统将能够同时运行成千上万个独立的进程。Phoenix 则是一套 Elixir Web 框架,能够支持高吞吐量,并允许开发者在各个独立的 Exlixir 进程当中处理各项 HTTP 请求。

我们将上述方法结合起来,充分利用其各自优势,希望能够切实满足自身需求:

Puppeteer 用于实现预渲染,Phoenix 则用于实现服务器端渲染

  • Puppeteer 在构建时中按照我们预期的方式对 React 页面进行预渲染,并将结果保存为 HTML 文件(来自 PRPL 模式的 app shell)。

我们可以继续构建一款简单的浏览器 React 应用程序,并在无需等待最终用户设备 JavaScript 处理过程的同时获得快速初始页面加载效果。

  • 我们的 Phoenix 应用负责实现页面预渲染,并以动态方式将实际内容注入至 HTML。这就使得内容的 SEO 友好性大幅提升,让按需处理大量多种页面成为可能,并显著降低了扩展难度。

  • 客户端接收并立即开始显示 HTML,而后由 Hydration 将 React DOM 状态持续作为常规 SPA。如此一来,我们就构建起了高度交互的应用程序,并可访问各项 JavaScript 浏览器功能。

利用 Puppeteer 建立预渲染架构,利用 Phoenix 进行服务器端渲染,React 则在客户端上实现 hydration

网络

内容交付网络 (CDN)

利用 CDN 可帮助我们实现内容缓存,并加速其在全球范围内的交付速度。我们选择了 Fastly.com,其目前处理着全球超过 10% 的请求总量,并得到 GitHub、Stripe、Airbnb 以及 Twitter 等诸多厂商的青睐。

Fastly 允许我们编写定制化缓存,并可利用 VCL 配置语言建立路由逻辑。下面,我们将具体聊聊基础请求流如何根据路由、请求头等因素分步起效:

VCL 请求流

提高性能的另一个选项是配合 Fastly 在边缘位置使用 WebAssembly(WASM)。大家可以将其视为一种无服务器模式,只是处于边缘位置;所使用的语言则包括 C、Rust、Go 以及 TypeScript 等等。Cloudflare 就拥有一个类似的项目,用于在 Workers 上支持 WASM。

缓存

尽可能多地利用缓存处理请求是改善性能水平的关键所在。立足 CDN 层级进行缓存,将能够更快地为新用户提供响应。而通过发送 Cache-Control 头进行缓存,则可加快浏览器中重复请求的响应速度。

大多数构建工具(例如 Webpack)允许用户向文件名当中添加哈希值。由于指向这些文件的任何变更都会产生新的输出文件名,因此大家可以安心将文件添加至缓存当中。

通过 HTTP/2 进行文件缓存与编码

GraphQL 缓存

发送 GraphQL 请求的一种常见方法,就是利用 POST HTTP 方法。而我们选择了立足 Fastly 层级对部分 GraphQL 请求进行缓存:

  • 我们的 React 应用会标注出那些可进行缓存的 GraphQL 查询。

  • 在发送 HTTP 请求之前,我们以请求本体为基础构建一条附加 URL 参数,其中包含 GraphQL 查询与变量(我们配合 Apollo Client 使用自定义 fetch)。

  • 在默认情况下 ,Varnish(与 Fastly)会使用完整的 URL 作为缓存密钥的一部分。

  • 这意味着我们可以通过请求本体当中的 GraphQL 查询不断发送 POST 请求,并在无需接触服务器的前提下立足边缘位置完成缓存。

利用一条 SHA256 URL 参数发送 POST GraphQL 请求

以下是其它一些值得参考的潜在 GraphQL 缓存策略:

  • 服务器端缓存:立足解析器层级或者通过模式标注对全部 GraphQL 请求进行缓存。

  • 利用持久化 GraphQL 查询并发送 GET /graphql/:queryId 以使用 HTTP 缓存机制。

  • 利用自动化工具(例如 Apollo Server 2.0)或者 GraphQL 专用型 CDN(例如 FastQL)实现不同 CDN 的整合。

编码

目前,所有主流浏览器都支持利用 gzip 加 Content-Encoding 标头进行数据压缩。这意味着面向浏览器的发送数据量更低,从而带来更快的内容传递速度。此外,如果浏览器支持,大家也可以尝试使用效率更高的 brotli 压缩算法。

HTTP/2 协议

HTTP/2 是 HTTP 网络协议的新版本(DevConsole 中简称为 h2)。由于存在着以下几项与 HTTP/1.x 版本间的显著差别,切换至 HTTP/2 能够带来性能提升:

  • HTTP/2 为二进制,而非文本式。因此其解析效率更高,也更加紧凑。

  • HTTP/2 具有多路复用属性,这意味着 HTTP/2 可以通过单一 TCP 连接发送多项请求。如此一来,我们就不必担心每主机浏览器连接限制以及域名分片等问题。

  • 其利用标头压缩机制减少请求 / 响应的实际体积。

  • 允许服务器主动推送响应。这项功能拥有诸多有趣的实际应用方式。

HTTP/2 Server Push

由于给现有工具及生态系统(例如 rack)引入了一系列颠覆性的变更,很多编程语言与库并不能完全支持 HTTP/2 的全部功能。但即便如此,我们仍然可以在部分合适的场景中使用 HTTP/2。举例来说:

  • 利用 HTTP/2 在常规 HTTP/1.x 服务器之前设置一套 h2o 或者 nginx 代理服务器。Puma 与 Ruby on Rails 能够发送 Early Hints,从而在一定的限制条件下启用 HTTP/2 Server Push。

  • 利用支持 HTTP/2 的 CDN 交付静态资产。例如,我们可以使用这种方法将字体以及一部分 JavaScript 文件推送至客户端。

HTTP/2 推送字体

对 JavaScript 以及 CSS 的推送功能同样非常实用。但请注意不要过度推送,您可点击此处了解一些相关问题:https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/

浏览器中的 JavaScript

包大小预算

JavaScript 性能优化中的头号规则就是,不要使用 JavaScript。

—— 我自己

如果您已经拥有现成的 JavaScript 应用程序,那么设置预算规则能够提高包大小的可见性,同时确保全部内容都可容纳于同一页面当中。超出预算后,开发人员则需要谨慎考虑并尽量防止规模进一步增长。以下是预算设置方面的相关示例:

  • 根据您的实际需求或推荐值设定数值。例如,不得大于 170 KB 否则压缩 JavaScript。

  • 利用现有包大小作为基准,或者尝试对其进行削减——例如下调 10%。

  • 尝试让网站拥有高于竞争对手的速度,并以此为依据设定预算。

您可以使用 bundlesize 工具包或者 Webpack 性能提示与限制进行预算跟踪:

Webpack 性能提示与限制

消除依赖性

Sidekiq 曾在一篇博文中提到:“代码越少,运行速度越快。代码越少,bug 就越少。代码越少,占用的内存量就越低。代码越少,理解起来就越轻松。”

遗憾的是,实际 JavaScript 场景中往往存在着不计其数的依赖关系。您可以试试:ls node_modules | wc -l。

在某些情况下,添加依赖性是种必然的选择。在这种情况下,依赖性的包大小应该被视为决定您实际工具包选择的重要依据。我强烈建议大家使用 BundlePhobia:

BundlePhobia 能够提示将 npm 工具包添加至您数据包中带来的实际成本

代码拆分

使用代码拆分是另一种能够显著提高 JavaScript 性能的好办法。其本质在于分解代码片段并仅向用户交付当前所需要的部分。以下是关于代码拆分的相关示例:

  • 在不同的 JavaScript 代码块间分别加载路由机制。

  • 拆分那些在页面中无法立即显示的部分,例如弹出框以及页面下方的页脚。

  • Polyfills 与 ponyfills 可支持全部主流浏览器当中的各最新浏览器功能。

  • 利用 Webpack 的 SplitChunksPlugin 防止代码重复。

  • 按需定位文件,以避免一次性发送所有受支持的语言。

您可以利用 Webpack 动态导入以及 React.lazy 配合 Suspense 实现代码拆分。

利用动态导入以及 React.lazy 配合 Suspense 实现代码拆分。

相较于默认导出,我们构建的函数可取代 React.lazy 以支持点名导出。

Async 与 defer 脚本

目前,全部主流浏览器皆在 script 标签上支持 async 与 defer 属性:

加载JavaScript的不同方式

几种不同的 JavaScript 加载方式:

  • 内联脚本适用于加载小体积、高关键度 JavaScript 代码。

  • 当您的用户或者任何其它脚本(例如分析脚本)不再需要某些特定脚本时,大家可以将 async 与这些脚本配合使用以避免 HTML 解析阻塞。

  • 从性能角度来看,将 defer 与脚本配合使用能够有效提升非关键 JavaScript 代码的抓取与执行效率,且避免发生 HTML 解析阻塞。此外,这种做法还能够在调用脚本时保证执行顺序,从而确保不同脚本间存在依赖性时实时与预期相符的执行效果。

下面来看 head 标签下不同脚本间的可视化差异:

几种不同的脚本抓取与执行方式

图像优化

虽然与 100 KB 的图像相比,100 KB 的 JavaScript 代码明确会带来更高的性能成本,但我们同样有必要重视对图像内容的优化调整。

削减图像大小的有效手段之一,是在适用的浏览器当中采用更加轻量化的 WebP 图像。对于那些无法支持 WebP 的浏览器,大家则可以采取以下几种策略:

  • 回退至常规的 JPEG 或者 PNG 格式(某些 CDN 会根据浏览器的 Accept 请求标头自动执行)。

  • 在检测浏览器的支持情况后,加载并使用 WebP polyfill。

  • 利用 Service Workers 监听 fetch 请求,并在支持时利用 WebP 变更实际 URL。

WebP 图像

仅当图像位于视图当中或者附近时才进行内容加载,堪称多图像初始页面加载过程中效果最显著的提速手段之一。您可以在受支持的浏览器当中使用 InterpObserver 功能,也可以利用其它一些替代性工具实现相同的结果——例如 react-lazyload。

在滚动过程中进行图像的延迟加载

其它一些图像优化策略还包括:

  • 降低图像质量以减小体积。

  • 调整大小并加载最小图像。

  • 利用 Srcset 图像属性自动在高分辨率显示器上加载高质量图像。

  • 利用渐进式图像快速显示图像的模糊版本。

常规图像与渐进图像之间的加载效果差异

大家也可以考虑使用通用型 CDN 或者图像专用 CDN,其通常会直接提供与图像相关的优化功能。

资源提示

资源提示(Resource hints) 允许我们优化资源交付、降低往返次数,同时获取资源以实现页面浏览过程中的内容交付提速。

带有 link 标签的资源提示

  • Preload 会在当前页面实际使用之前,通过后台预先下载高优先级资源。

  • Prefetch 的功能与 preload 类似,用于抓取资源并进行缓存,但仅供用户后续导航使用(低优先级)。

  • Preconnect 允许 HTTP 请求被实际发送至服务器之前即设置预连接。

提前进行预连接以避免 DNS、TCP 以及 TLS 往返延迟

当然,prerender 以及 dns-prefetch 等其它一些资源提示同样非常重要。其中一部分资源提示可在响应标头中进行指定。需要提醒大家的是,请务必小心使用资源提示。一旦开始滥用,您的页面中可能包含大量不必要的请求并快速下载过量数据,这种情况显然不利于使用蜂窝数据的移动用户。

总结

应用程序的性能改善之路代表着一个永远尽头的过程,且通常要求我们在整个堆栈当中持续作出更改。

每次看到下面这段视频,我总会想起你们努力减少应用包大小的样子。

——我的同事

马上把一切不需要的东西从飞机上扔下去!——电影《珍珠港》

以下列出了我们已经使用或者计划尝试的其它一些潜在性能改进思路:

  • 使用 Service Workers 进行缓存、离线支持以及主线程分摊。

  • 通过关键 CSS 内联或者函数式 CSS 实现数据包的长效“瘦身”。

  • 使用 WOFF2 字体替代 WOFF 字体(仅举一例,字体变更最高可带来 50% 压缩效果)。

  • 确保 browserslist 的定期更新。

  • 利用 webpack-bundle-analyzer 直观分析构建块。

  • 优选较小的工具包(例如 date-fns)及插件(例如 lodash-webpack-plugin),从而缩小页面体积。

  • 尝试使用 preact、lit-html 或者 svelte。

  • 在 CI 中运行 Lighthouse。

  • 渐进式 hydration 与 React 流式设计。

另外还有更多令人兴奋的想法可供尝试。希望本文提出的信息及以下案例研究能够激发出大家改善应用程序性能的更多灵感:

  • 根据亚马逊方面的计算,单一页面 1 秒的响应延时每年可能造成 16 亿美元损失。链接地址:https://www.fastcompany.com/1825005/how-one-second-could-cost-amazon-16-billion-sales

  • 沃尔玛每缩短 1 秒加载时长,即可提升 2% 的客户转换率。每 100 毫秒的提升则可带来 1% 的收入增长。链接地址:https://wpostats.com/2015/11/04/walmart-revenue.html

  • 谷歌公司计算出,如果搜索结果显示速度减缓 0.4 秒,则每天搜索量将减少 800 万次。链接地址:https://www.fastcompany.com/1825005/how-one-second-could-cost-amazon-16-billion-sales

  • 品趣志的页面重构将等待时长缩短了 40%,SEO 流量增加了 15%,注册转换率亦提升 15%。链接地址:https://medium.com/@Pinterest_Engineering/driving-user-growth-with-performance-improvements-cfc50dafadd7

  • BBC 通过观察发现,网站加载时长每增加 1 秒钟,就会失去 10% 的用户。链接地址:https://www.creativebloq.com/features/how-the-bbc-builds-websites-that-scale

最后

好了,这就是整理的前端从入门到放弃的学习笔记,还有很多没有整理到,我也算是边学边去整理,后续还会慢慢完善,这些相信够你学一阵子了。

做程序员,做前端工程师,真的是一个学习就会有回报的职业,不看出身高低,不看学历强弱,只要你的技术达到应有的水准,就能够得到对应的回报。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

学习从来没有一蹴而就,都是持之以恒的,正所谓活到老学到老,真正懂得学习的人,才不会被这个时代的洪流所淘汰。

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值