前端性能优化到底该怎么做(下)— 直捣黄龙(一)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
.cn 域名,1个 12个月
简介: 前端性能优化到底该怎么做(下)— 直捣黄龙

image.png


前言

在上一篇 前端性能优化到底该怎么做(上)— 开门见山 一文中介绍了和前端性能优化相关的一些前置知识,那么本篇就针对优化方案进行总结,核心的方向还是上篇文章中提到的内容:

  • 保证资源更快的 加载速度:达到越快渲染越快,视图展现就越快
  • 保证视图更快的 渲染速度/交互速度:用户与页面交互,前提是页面要渲染出来,其次是页面需要尽早反馈,目的就是保证用户良好的体验性

其实将上述两点再进行翻译,那么其实指的就是 网络层面的优化浏览器层面的优化,这样看来其实前端性能优化方向还是很明确的,只不过明确的方向中还是会涉及不同方面的具体优化手段。

还是不得不回顾 从输入 URL 到页面加载完成 的核心过程:

  • 进行 DNS 解析
  • 建立 TCP 连接
  • 客户端发送 HTTP 请求
  • 服务端响应 HTTP 资源
  • 浏览器获取响应内容,进行解析和渲染

从上述的内容来看,不难发现每一步都是需要消耗一定的时间,那么优化的方向就可以围绕着这些内容来考虑。

长文预警❗️❗️❗️ 长文预警❗️❗️❗️ 长文预警❗️❗️❗️ 长文预警❗️❗️❗️

如何保证资源更快的加载速度?

下面内容主要针对 DNS 解析TCP 连接HTTP 请求/响应 等阶段来谈的优化,核心优化核心其实就是 网络层面

使用 dns-prefetch 减少 DNS 的查询时间

dns-prefetch 能够 提前解析 后续可能会用到的 不同域的域名,使解析结果 缓存到系统缓存 中,缩短 DNS 解析时间以提高网站的访问速度。

比如在掘金中的体现如下:

image.png

扩展DNS 解析的核心过程

当浏览器访问一个域名时需解析一次 DNS,以获得对应域名的 IP 地址:

  • 浏览器 会从自身的 缓存中 查询是否存在对应域名的 IP 地址,若存在返回,若不存在进入下一步
  • 客户机查询操作系统中的 /etc/hosts 文件中查询是否有对应域名的 IP 地址,若存在则返回,若不存在进入下一步
  • 客户机请求 本地域名服务器(LDNS) 进行解析,本地域名服务器收到客户机的请求后,先查询自己的缓存信息是否有对应域名的 IP 地址,若存在返回结果,没有则进行下一步
  • 本地域名服务器请求 根域名服务器 解析该域名,根域名告诉本地域名服务器去找对应的 一级域名服务器
  • 本地域名服务器请求一级域名服务器解析这个域名,一级域名服务器告诉它去找对应的 二级域名服务器
  • 本地域名服务器请求二级域名服务器解析这个域名,二级域名服务器告诉它去找对应的 子域名服务器
  • 本地域名服务器请求子域名服务器解析这个域名,子域名服务器返回对应的 IP 地址
  • 本地域名服务器将 IP 地址记录到缓存中,并返回给客户机(会缓存起来),客户机根据收到的 IP 地址访问该网站

使用 preconnect 提前建立连接

preconnect 的作用是提前和第三方资源建立连接,设置了它浏览器就会做好早期的连接工作,但这个连接通常只会维持 10 s

比如在当前域请求一个资源前,可能会涉及 DNS 寻址、TLS 握手、TCP 握手、重定向等,这过程也会花费一定的时间。

比如在掘金中的体现如下:

image.png

使用 preload / prefetch 预先加载资源

preload

preload 的作用是提前加载页面对应的 关键资源 加快页面的渲染,preload 的优先级顺序和 as 属性相关,具体可见

注意as 属性一定要设置,除了上面提到的设置优先级外,还涉及到浏览识别的问题:如果没有设置 as 属性,后续遇到该请求就会被作为一个 XHR 请求,把意味着资源预加载的功能可能会失效,因为可能会每次都发起新的请求获取

比如在掘金中的体现如下:

image.png

比如在 vue-cli 的默认 webpack 配置,如下:

image.png

prefetch

preload 是对资源的预加载,它虽提前加载但只在需要执行时执行,即这个资源一定是当前页面所需要的资源,如果是需要为下一个页面提前加载资源,那么应该使用 prefetch,它会在 浏览器空闲时 下载资源。

比如在 vue-cli 的默认 webpack 配置,如下:

image.png

压缩资源体积

资源是需要通过 http 数据包的方式在网络中进行传输的,那么只要能减少传输数据包的体积,也是能够使得资源更快到达客户端,这也是压缩资源体积的核心目的。

HTTP 压缩

HTTP 压缩中一个典型代表就是 gzip,它是一种优秀的压缩算法,可对 http 请求中的一些文件资源进行压缩处理,一般来讲是要在服务端处理的,可通过在响应头中设置 Content-encoding: gzip 表示当前资源使用的压缩方式(如:gzip、deflate、br 等),便于客户端使用正确的方式解压。

注意gzip 并不是万能的,它不能保证针对每个文件的压缩都能使其体积变小,关于 Content-Encoding 的内容 可点此查阅,或者可参考 content-encoding 除了gzip之外,你还知道哪些?

比如在京东中的体现:

image.png

比如在掘金中的体现:

image.png

Webpack 压缩

HTTP 压缩 不就够了吗?为什么还需要 Webpack 压缩?

首先必须要明确的是压缩的过程本身就是会消耗时间的,如果所有资源都等到被访问的时候再由服务端进行压缩,在压缩完成之前客户端还是得处于等待状态,即仍 不能保证资源以最快的速度到达客户端

那么优化方案就是将压缩资源的时间放到打包构建中,毕竟只有真正需要发布线上生产环境时才需要执行一系列的打包优化的操作,而这相比于 http请求/响应 速度,稍微延长产物打包时间没有什么大问题。

下面会列举一些 Webpack 插件,但并不会去讲其中的具体用法,因为这些只是达到目的的不同方案而已,每个方案要是细讲都可以独占一篇文章,在这是没有必要的,具体用法可自行查阅。

使用 CompressionPlugin 压缩文件

image.png

webpack 文档 提供插件合集中就包含了该插件,它的作用就是:Prepare compressed versions of assets to serve them with Content-Encoding.

使用 HtmlWebpackPlugin 压缩 HTML 文件

image.png

通常我们需要 HtmlWebpackPlugin 插件来生成对应 HTML 或 对已有的 HTML 模板自动注入 webpack bundles 资源,除此之外,它还可配置 minify 选项实现压缩模板的目的。

可以在 vue 项目下执行 vue inspect --mode production > webpack.config.js 来查看脚手架的默认 webpack 配置内容,比如:

image.png

使用 SplitChunksPlugin 自定义分包策略

Webpack 默认会将尽可能多的模块代码打包在一起,这种默认规则的带来的优点和缺点都很明显:

  • 优点:能减少最终页面的 HTTP 请求数
  • 缺点:
  • 页面初始代码包过大,影响首屏渲染性能
  • 无法有效应用浏览器缓存

SplitChunksPluginWebpack 4 之后内置实现的最新分包方案,与 Webpack 3 中的 CommonsChunkPlugin 相比,它能够基于一些更灵活、合理的启发式规则将 Module 编排进不同的 Chunk,最终构建出 性能更佳、缓存更友好 的应用产物。

比如在 vue-cli 的默认 webpack 配置,如下:

image.png

使用 MiniCssExtractPlugin 抽离和压缩 CSS

MiniCssExtractPlugin 会将 CSS 提取到单独的文件中,为每个包含 CSSJS 文件创建一个 CSS 文件,并且支持 CSSSourceMaps按需加载

比如在 vue-cli 的默认 webpack 配置,如下:

image.png

image.png

使用 ImageMinimizerWebpackPlugin 压缩图片资源

图片仍是一个 Web 应用中的必不可少的资源,而图片资源的体积也是首屏页面加载的瓶颈之一,因此,压缩图片也是性能优化需要考虑的内容。

ImageMinimizerWebpackPlugin 可用于使用 优化/压缩 所有图像,它可以支持 无损(不损失质量)有损(质量下降) 两种模式的压缩方式。

image.png

通过 Tree Shaking 移除无用代码

Tree Shaking 依赖于 ES6 模块语法的 静态结构 特性(如: importexport),当 webpack 的模式 mode"production" 时,就可以启用 更多优化项,包括 压缩代码Tree Shaking

但同时我们就必须保证:

  • 尽量使用 ES6 模块语法,即 importexport
  • 保证没有 编译器(如:babel)将对应的 ES6 模块语法转换为 CommonJS 的语法(如:@babel/preset-env 的默认行为)
  • 可在项目的 package.json 文件中添加 "sideEffects" 属性,标识当前内容是否存在副作用操作
  • 可在通过 /*#__PURE__*/ 注释,将函数调用标记为无副作用


目录
相关文章
|
存储 缓存 JavaScript
前端性能优化到底该怎么做(下)— 直捣黄龙(二)
前端性能优化到底该怎么做(下)— 直捣黄龙
179 0
|
2月前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
177 2
|
2月前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
48 0
|
2月前
|
人工智能 自然语言处理 运维
前端大模型应用笔记(一):两个指令反过来说大模型就理解不了啦?或许该让第三者插足啦 -通过引入中间LLM预处理用户输入以提高多任务处理能力
本文探讨了在多任务处理场景下,自然语言指令解析的困境及解决方案。通过增加一个LLM解析层,将复杂的指令拆解为多个明确的步骤,明确操作类型与对象识别,处理任务依赖关系,并将自然语言转化为具体的工具命令,从而提高指令解析的准确性和执行效率。
|
2月前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
2月前
|
机器学习/深度学习 弹性计算 自然语言处理
前端大模型应用笔记(二):最新llama3.2小参数版本1B的古董机测试 - 支持128K上下文,表现优异,和移动端更配
llama3.1支持128K上下文,6万字+输入,适用于多种场景。模型能力超出预期,但处理中文时需加中英翻译。测试显示,其英文支持较好,中文则需改进。llama3.2 1B参数量小,适合移动端和资源受限环境,可在阿里云2vCPU和4G ECS上运行。
124 1
|
2月前
|
前端开发 算法 测试技术
前端大模型应用笔记(五):大模型基础能力大比拼-计数篇-通义千文 vs 文心一言 vs 智谱 vs 讯飞vsGPT
本文对比测试了通义千文、文心一言、智谱和讯飞等多个国产大模型在处理基础计数问题上的表现,特别是通过链式推理(COT)提示的效果。结果显示,GPTo1-mini、文心一言3.5和讯飞4.0Ultra在首轮测试中表现优秀,而其他模型在COT提示后也能显著提升正确率,唯有讯飞4.0-Lite表现不佳。测试强调了COT在提升模型逻辑推理能力中的重要性,并指出免费版本中智谱GLM较为可靠。
前端大模型应用笔记(五):大模型基础能力大比拼-计数篇-通义千文 vs 文心一言 vs 智谱 vs 讯飞vsGPT
|
3月前
|
SpringCloudAlibaba JavaScript 前端开发
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
分布式组件、nacos注册配置中心、openfegin远程调用、网关gateway、ES6脚本语言规范、vue、elementUI
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
|
4月前
|
存储 前端开发 JavaScript
前端语言串讲 | 青训营笔记
前端语言串讲 | 青训营笔记
50 0
|
6月前
|
JSON 前端开发 JavaScript
前端Ajax、Axios和Fetch的用法和区别笔记
前端Ajax、Axios和Fetch的用法和区别笔记
115 2