资源合并与压缩
- 理解减少 http 请求数量和减少请求资源大小两个优化要点
- 掌握压缩于合并的原理
- 掌握通过在线网站和 fis3 两种实现压缩与合并的方法
http 清求的过程及潜在的性能优化点
深入理解 http 请求的过程 是前端性能优化的核心
- dns 是否可以通过缓存减少 dns 查询时间 ?
- 网络请求的过程走最近的网络环境 ?
- 相同的静态资源是否可以缓存 ?
- 能否减少请求 http 请求大小 ?
- 减少 http 请求
- 服务端渲染
html 压缩
HTML 代码压缩就是压缩这些在文本文件中有意义,但是在 HTML 中不显示的字符,包括空格,制表符,换行符等,还有一些其他意义的字符,如 HTML 注释 也可以被压缩。
- 使用在线网站进行压缩
- nodejs 提供了 html-minifier 工具等 npm 工具
- 后端模板引擎渲染压缩
HTML 优化
- 减少 iframes 使用
- 压缩空白符, 空行
- 避免节点深层级嵌套 div 盒子
- 避免 table 布局
- 删除注释
- css&Javascript 尽量外链
- 删除元素默认属性
- 单闭合标签 li img 不用闭合?
CSS 压缩
- 使用在线网站进行压缩
- html-minifier 工具对 html 中的 css 进行压缩
- 使用 clean-css 对 css 进行压缩
CSS 对性能的影响
nth-child
css 优化
- 降低 CSS 对渲染的阻塞, 先加载首屏资源
- 利用 GPU 进行完成动画
- 使用 li{contain: layout}?还有?
- 使用 font-display 属性
Js 压缩与混乱
- 无效字符的删除
- 剔除注释
- 代码语义的缩减和优化
- 代码保护
如何操作:
- 使用在线网站进行压缩
- html-minifier 工具对 html 中的 js 进行压缩
- 使用 uglifyjs2 对 js 进行压缩
- 使用 WebPack 对 JS 在构建时压缩
文件合并
存在的问题:
- 首屏渲染问题
- 缓存失效问题
建议:
-
公共库合并
-
不同页面的 js 分别合并( 针对单页面, 异步加载组件 )
-
见机行事, 随机应变
-
使用在线网站进行文件合并
-
构建阶段使用 nodejs 实现文件合并
使用 fis3 构建工具自动压缩合并
图片优化
图片优化- 图片加载优化
- 原生的图片懒加载方案 < img loading="lazy"
- 第三方图片懒加载方案
verlok/lazyload
yall.js
Blazy使用渐进式图片
使用响应式图片
- Srcset 属性的使用
- Sizes 属性的使用
- picture 的使用
不同格式图片常用的业务场景
- jpg 有损压缩, 压缩率高, 不支持透明。
- 优点: 压缩比很高, 颜色色彩画质好。缺点: logo 不用 jpeg,边缘感粗糙
- 使用场景: 轮播图
- png:优点: 支持透明背景图片(线条, 边缘, 细腻程度),浏览器兼容好。缺点: 保留细节, 体积大【小的图片. 图标 logo】
- webp 压缩程度更好, 在 ios webview 有兼容性问题 ( 安卓全部 )
- svg 矢量图, 内容内嵌, 相对较小, 图片样式相对简单的场景 ( logo )
css 雪碧图
- 减少网站 http 请求数量
- 缺点: 整合图片比较大时, 一次加载比较慢
image inline
- 将图片的内容内嵌到 html 当中
- 减少网站 http 请求数量
矢量图
- svg 进行矢量图的绘制
- 使用 iconfont 解决 icon 问题
在安卓下使用 webpp
- WebP 的优势体现在它具有更优的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量;
- 同时具备了无损和有损的压缩模式、Alpha 透明以及动画的特性,在 JPEG 和 PNG 上的转化效果都非常优秀、稳定和统一。
- 比 png 体积更小
- ie 不支持 兼容性不好, 80%
css 和 js 的装载与执行
HTML 页面加载渲染的过程
- 理解浏览器端 html, css, js 的加载过程
- 结合 chrome 的能力学习掌握 css, js 加载过程中的优化点
特点
- 顺序执行, 并发加载
- 词法分析
- 并发加载
- 并发上限
- 是否阻塞
- 依赖关系
- 引入方式
css 阻塞?
- css head 中阻塞页面的渲染
- css 阻塞 js 的执行
- css 不阻塞外部脚本的加载
js 阻塞?
- 直接引入的 js 阻塞页面的渲染
- js 不阻塞资源的加载
- js 顺序执行, 阻塞后续 js 逻辑的执行
懒加载与预加载
懒加载原理
- 图片进入可视区域之后请求图片资源(动态图片的 src 的地址是否真实的, 否: 可能为 1px 占位符) image 标签的 src 被设置后, 就会请求资源
- 对于电商等图片很多,页面很长的业务场景适用
- 减少无效资源的加载
- 并发加载的资源过多会阻塞 js 的加载,影响网站的正常使用
预加载原理
- 图片等静态资源在使用之前的提前请求
- 资源使用到时能从缓存中加载,提升用户体验
- 页面展示的依赖关系维护
懒加载原生 js 和 zepto.lazyload
需要监听 scroll 事件,在 scroll 事件的回调中,去判断我们的懒加载的图片是否进入可视区域
预加载原生 js 和 PreloadJS 实现
-
1.使用 img 标签,style 样式 display: none
-
2.使用 Image 对象
var image=new Image()
image.src="https://xxxx" -
3.使用 XMLHttpRequest 对象
-
4.使用 PreloadJS
new createjs.LoadQueue(false)
??为啥要传参 false
二者本质上是控制图片加载的时机
权衡浏览器本身具有加载资源的能力,让这能力饱和,充分使用,好让前端性能优化,有更好的体验
重绘和回流
回流与重绘,如何避免布局抖动
布局和绘制
- 渲染树只包含网页需要的节点
- 布局计算每个节点精确的位置和大小 -“盒模型”
- 绘制是像素化每个节点的过程
避免布局抖动(layout thrashing)
- 使用 FastDom 批量对 DOM 的读写操作(eg:动态修改图片宽度)
css 性能让 javascript 变慢?
- eg: js 写了个死循环, 页面突然卡死,chome 无响应
- css 核心会影响页面样式的展示,
- 频繁触发重绘与回流,会导致 UI 频繁渲染,最终导致 js 变慢
- 一个线程=>JavaScript 解析
- 一个线程=>UI 渲染
什么是重绘与回流
回流必将引起重绘,而重绘不一定会引起回流
回流
- 当 render tree 中的一部分(或全部) 因为元素的规模尺寸, 布局, 隐藏等改变而需要重新构建。这就成为回流(reflow)
- 当页面布局和几何属性改变时就需要回流
影响回流的操作
- 添加/删除元素
- display:none
- 移动元素位置
- 操作 styles
- offsetLeft,scrollTop, clientWidth
- 修改浏览器大小,字体大小
重绘
- 当 render tree 中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如 background-color。则就叫称为重绘。
避免重绘回流的两种方法
1.避免使用触发重绘, 回流的 CSS 属性
- ①触发页面重布局的属性(回流)
- 盒子模型相关属性会触发重布局
- 定位属性及浮动也会重发重布局
- 改变节点内部文字结构也会触发重布局
- ②只触发重绘的属性
2.将重绘, 回流的影响范围限制在单独的图层之内
- 将频繁重绘回流的 DOM 元素单独作为一个独立图层,那么这个 DOM 元素和重绘和回流的影响只会在这个图层中
如何将 DOM 元素变成新的独立图层?
Chrome 创建图层的条件
- 1.3D 或透视变换 CSS 属性(perspective transform)
- 2.使用加速视频解码的<video 节点
- 3.拥有 3D(WebGL)上下文或加速的 2D 上下文的<canvas 节点
- 4.混合插件(如 Flash)
- 5.对自己的 opacity 做 CSS 动画或使用一个动画 webkit 变换的元素
- 6.拥有加速 CSS 过滤器的元素
- 7.元素有一个包含复合层的后代节点(一个元素拥有一个子元素,该子元素在自己的层里)
- 8.元素有一个 z-index 较低且包含一个复合层的兄弟元素(换句话说就是该元素在复合层上面渲染)
实战优化点总结
- 1.用 translate 替代 top 改变 ( top 会触发回流但是 translate 不会 )
- 2.用 opacity 替代 visibility (减少重绘)
- 3.不要一条一条地修改 DOM 的样式, 预先定义好 class(样式), 然后修改 DOM 的 className
- 4.把 DOM 离线后修改,比如:先把 DOM 给 display:none (有一次 Reflow),然后你修改 100 次,然后再把它显示出来
- 5.不要把DOM 结点的属性值放在一个循环里当成循环里的变量 ( offsetHeight offsetWidth )
- 6.不要使用 table 布局,可能很小的一个小改动会造成整个 table 的重新布局 ( 尽量使用 div )
- 7.动画实现的速度的选择 ( 合适动画时间 )
- 8.对于动画新建图层
- 9.启用 GPU 硬件加速
1.用 translate 替代 top 改变 2.用 opacity 替代 visibility
- opacity: 没有 paint 的过程, 因为 paint 的过程是生成图层,但是 opacity 实际上是直接改变的图层的 alpha 通道, 所以不涉及图层的重绘
<!DOCTYPE html>
<html lang="en">
<head>
<title>1.用 translate 替代 top 改变 2.用 opacity 替代 visibility</title>
<meta charset="UTF-8"></meta>
<style>
#rect {
width: 100px;
height: 100px;
background-color: blue;
/*1.*/
/*position: relative;*/
/*top: 0;*/
/*transform: translateY(0);*/
/*2*/
opacity: 1;
transform: translateZ(0);
}
</style>
</head>
<body>
<div id="rect"></div>
<script>
setTimeout(() => {
// document.getElementById('rect').style.transform = 'translateY(100px)'
// 2
document.getElementById('rect').style.opacity = '0'
}, 2000)
</script>
</body>
</html>
3.单独 class 样式
<!DOCTYPE html>
<html lang="en">
<head>
<title>3.不要一条一条地修改 DOM 的样式, 预先定义好 class, 然后修改 DOM 的 className</title>
<meta charset="UTF-8"></meta>
<style>
#rect {
position: relative;
width: 100px;
height: 100px;
background-color: blue;
opacity: 1;
}
#rect.action{
/*#rect.action 提高样式优先级*/
width: 200px;
height: 300px;
left: 300px;
top: 200px;
}
</style>
</head>
<body>
<div id="rect"></div>
<script>
setTimeout(() => {
document.getElementById('rect').className = 'action'
}, 2000)
</script>
</body>
</html>
5.不要把 DOM 结点的属性值放在一个循环里当成循环里的变量
<script>
var doms=[]//通过选择器选择出了一个 dom 元素的数组
var domsTop=[]
var clientHeight=document.body.clientHeight//获取可视区域的高度
//去根据当前页面的可视区域的高度,去计算这个 dom 元素的位置
for(var i=0;i<doms.length;i++){
// domsTop.push(document.body.clientHeight+i*100)//浏览器的布局缓存被频繁刷新,导致每次访问 DOM 属性时都需要重新计算,从而影响性能
domsTop.push(clientHeight+i*100)
}
</script>
7.动画实现的速度的选择
<!DOCTYPE html>
<html lang="en">
<head>
<title>7.动画实现的速度的选择 </title>
<meta charset="UTF-8"></meta>
<style>
#rect {
position: relative;
top: 0;
left: 0;
width: 100px;
height: 100px;
background-color: blue;
opacity: 1;
}
</style>
</head>
<body>
<div id="rect"></div>
<script>
var distance = 0;
setInterval(()=>{//平滑度高, 流畅, 但是耗性能高,回流重绘次数多
distance ++;
document.getElementById('rect').style.top=distance+'px';
document.getElementById('rect').style.left=distance+'px';
},100)
</script>
</body>
</html>
8will-change 是一个 CSS 属性,
- 用于告诉浏览器某个元素在未来可能会发生哪些变化。这可以帮助浏览器优化渲染性能,提前做一些准备工作,从而提高性能。
will-change: transform; 和 transform: translateZ(0);
这段 CSS 代码用于优化动画性能:
- will-change: transform:提前告知浏览器元素将要发生变换,让浏览器预先进行性能优化
9.启用 GPU 硬件加速
-
transform: translateZ(0):创建硬件加速上下文,将元素提升到新的合成层,避免重绘和回流,提高动画流畅度
两者结合使用可以显著提升 CSS 动画和变换的渲染性能。 -
transform: translate3d(0,0,0): 不能滥用,
创建一个 3D 变换上下文
强制浏览器将该元素提升到独立的合成层
触发 GPU 硬件加速,使动画更加流畅
浏览器存储
cookies
- 因为 HTTP 请求无状态,所以需要 cookie 去维持客户端状态
- cookie 的生成方式:
- http response header 中的 set-cookie
- js 中可以通过 document.cookie 可以读写 cookie
- 两种作用
- ①用于浏览器端和服务器端的交互
- ②客户端自身数据的存储
- 过期时间:expire
cookie 存储的限制
- 仅仅作为浏览器存储,大小 4KB 左右
- 需要设置过期时间 expire
- cookie 存储数据能力被 localstorage 替代
- cookie 不支持 js 读写----httponly
- cookie 中在相关域名下面--cdn 的流量损耗
- 解决方法: cdn 的域名 和主站的域名要分开
localStorage
- HTML5 设计出来专门用于浏览器存储的
- 大小为 5M 左右
- 仅在客户端使用,不和服务端进行通信
- 接口封装较好
- 浏览器本地缓存方案
sessionStorage
- 会话级别的浏览器存储
- 大小为 5M 左右
- 仅在客户端使用,不和服务端进行通信
- 接口封装较好
- 对于表单信息的维护 (多页面切换时)
IndexedDB
- IndexedDB 是一种低级 API,用于客户端存储大量结构化数据。该 API 使用索引来实现对该数据的高性能搜索。虽然 WebStorage 对于存储较少量的数据很有用,但对于存储更大量的结构化数据来说,这种方法不太有用。IndexedDB 提供了一个解决方案。
- 为应用创建离线版本
PWA
- 可靠:在没有网络的环境中也能提供基本的页面访问,而不会出现“未连接到互联网”的页面
- 快速:针对网页渲染及网络数据访问有较好优化
- 融入(Engaging):应用可以被增加到手机桌面,并且和普通应用一样有全屏、推送等特性。
- lighthouse
Service Worker
- 是一个脚本,浏览器独立于当前网页,将其在后台运行,为实现一些不依赖页面或者用户交互的特性打开了一扇大门。在未来这些特性将包括推送消息,背景后台同步,geofencing(地理围栏定位),但它将推出的第一个首要特性,就是拦截和处理网络请求的能力,包括以编程方式来管理被缓存的响应。
- 可以实现:
- 1.使用缓存完成当前 PWA 离线应用的能力
- 2.和主页面的通信,(页面中有非常大的数据处理,非常大的逻辑运算---不依赖页面或者用户交互的特性,可以在后台运行,不阻碍主线程的执行)
应用:
- 1.使用拦截和处理网络请求的能力,去实现一个离线应用
- 2.使用 Service Worker 在后台运行同时能和页面通信的能力, 去实现大规模后台数据的处理
Cache-Control
是 HTTP 协议中的一个响应头/请求头,用来控制缓存行为。它可以决定浏览器、CDN、代理服务器等中间缓存的存储方式和有效时间。
- max-age:
- 指定资源在 缓存中的最大存活时间(以秒为单位)。
- 在 max-age 有效期内,浏览器或代理会直接用缓存,不会去请求服务器。
- 1h: 3600s, 1 天 86400s,
- 0s 等价于 Expires: 0 [表示客户端只接受最新资源,不要用缓存。]
- s-maxage
仅共享缓存(CDN、代理)优先级比 max-age 高 - no-cache
不是“不缓存”,而是 可以缓存,但用之前必须向服务器确认是否过期。
它依赖 协商缓存(ETag / Last-Modified)。 - no-store
完全不缓存,连磁盘/内存都不保存(最严格,常用于敏感信息) - public
- 资源可以被 任何缓存 存储:浏览器缓存、代理缓存(CDN、代理服务器、反向代理等)。
- 默认情况下,大部分静态资源(图片、CSS、JS)都是 public。
- private
- 资源只能被 单个用户的浏览器缓存,共享缓存(CDN/代理)不能存。
- 适合和用户身份强相关的数据。
- 常用于 用户个人主页、购物车、账户信息 等。
Expires
- 是 HTTP/1.0 的缓存控制头,用于指定一个 绝对的过期时间(GMT 时间)。
- 在过期时间之前,浏览器或代理缓存可以直接从浏览器缓存取数据,不用去服务器请求。
last-modified 缺点
- 某些服务端不能获取精确的修改时间
- 文件修改时间改了, 但文件内容却没有变











