Appearance
五、性能解决
1、网络优化策略
- 减少 HTTP 请求数,合并
JS、CSS,合理内嵌CSS、JS - 合理设置服务端缓存,提高服务器处理速度。 (强制缓存、对比缓存)html
Expires/Cache-Control
Etag/if-none-match/last-modified/if-modified-since
- 避免重定向,重定向会降低响应速度 (301,302)
- 使用`dns-prefetch`,进行`DNS`预解析
- 采用域名分片技术,将资源放到不同的域名下。解决同一个域名最多处理6个TCP链接问题。
- 采用`CDN`加速加快访问速度。(指派最近、高度可用)
- `gzip`压缩优化 对传输资源进行体积压缩 (`html`,`js`,`css`)
```html
Content-Encoding: gzip加载数据优先级 :
preload(预先请求当前页面需要的资源)prefetch(将来页面中使用的资源) 将数据缓存到 HTTP 缓存中
html<link rel="preload" href="style.css" as="style" />
2、关键渲染路径

- 重排(回流)
Reflow: 添加元素、删除元素、修改大小、移动元素位置、获取位置相关信息 - 重绘
Repaint:页面中元素样式的改变并不影响它在文档流中的位置。
我们应当尽可能减少重绘和回流
(1)强制同步布局问题
JavaScript 强制将计算样式和布局操作提前到当前的任务中
html
<div id="app"></div>
<script>
function reflow() {
let el = document.getElementById("app");
let node = document.createElement("h1");
node.innerHTML = "hello";
el.appendChild(node);
// 强制同步布局
console.log(app.offsetHeight);
}
requestAnimationFrame(reflow);
</script>(2)布局抖动(layout thrashing)问题
在一段js代码中,反复执行布局操作,就是布局抖动
js
function reflow() {
let el = document.getElementById("app");
let node = document.createElement("h1");
node.innerHTML = "hello";
el.appendChild(node);
// 强制同步布局
console.log(app.offsetHeight);
}
window.addEventListener("load", function () {
for (let i = 0; i < 100; i++) {
reflow();
}
});(3)减少回流和重绘
- 脱离文档流
- 渲染时给图片增加固定宽高
- 尽量使用
css3动画 - 可以使用 will-change 提取到单独的图层中
3、静态文件优化
(1)图片优化
图片格式:
jpg:适合色彩丰富的照片、banner 图;不适合图形文字、图标(纹理边缘有锯齿),不支持透明度png:适合纯色、透明、图标,支持半透明;不适合色彩丰富图片,因为无损存储会导致存储体积大gif:适合动画,可以动的图标;不支持半透明,不适和存储彩色图片webp:适合半透明图片,可以保证图片质量和较小的体积svg格式图片:相比于jpg和jpg它的体积更小,渲染成本过高,适合小且色彩单一的图标;
图片优化:
避免空
src的图片减小图片尺寸,节约用户流量
img标签设置alt属性, 提升图片加载失败时的用户体验原生的
loading:lazy图片懒加载html<img loading="lazy" src="./images/1.jpg" width="300" height="450" />不同环境下,加载不同尺寸和像素的图片
html<img src="./images/1.jpg" sizes="(max-width:500px) 100px,(max-width:600px) 200px" srcset="./images/1.jpg 100w, ./images/3.jpg 200w" />对于较大的图片可以考虑采用渐进式图片
采用
base64URL减少图片请求采用雪碧图合并图标图片等
(2)HTML优化
- 语义化
HTML:代码简洁清晰,利于搜索引擎,便于团队开发 - 提前声明字符编码,让浏览器快速确定如何渲染网页内容
- 减少 HTML 嵌套关系、减少 DOM 节点数量
- 删除多余空格、空行、注释、及无用的属性等
- HTML 减少
iframes使用 (iframe会阻塞onload事件可以动态加载iframe) - 避免使用 table 布局
(3)CSS优化
建议
减少伪类选择器、减少样式层数、减少使用通配符
避免使用
CSS表达式,CSS表达式会频繁求值, 当滚动页面,或者移动鼠标时都会重新计算 (IE6,7)cssbackground-color: expression((new Date()) .getHours() %2 ? "red": "yellow");删除空行、注释、减少无意义的单位、
css进行压缩使用外链
css,可以对CSS进行缓存添加媒体字段,只加载有效的
css文件html<link href="index.css" rel="stylesheet" media="screen and (min-width:1024px)" />CSS contain属性,将元素进行隔离减少@import 使用,由于@import 采用的是串行加载
(4)CSS 书写顺序
建议遵循以下顺序:
js
// 1. 布局定位属性:(建议 display 第一个写,毕竟关系到模式)
display / position / float / clear / visibility / overflow
// 2. 自身属性:
width / height / margin / padding / border / background
// 3. 文本属性:
color / font / text-decoration / text-align / vertical-align / white- space / break-word
// 4. 其他属性(CSS3):
content / cursor / border-radius / box-shadow / text-shadow / background:linear-gradientcss
/* 一个示例 */
.jdc {
display: block;
position: relative;
float: left;
width: 100px;
height: 100px;
margin: 0 10px;
padding: 20px 0;
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
color: #333;
background: rgba(0, 0, 0, 0.5);
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-o-border-radius: 10px;
-ms-border-radius: 10px;
border-radius: 10px;
}(5)缩小样式计算范围
- 降低选择器的复杂性和深度
- 减少 dom 元素的数量和选择器的数量
(6)JS优化
- 通过
async、defer异步加载文件

- 减少 DOM 操作,缓存访问过的元素
- 操作不直接应用到 DOM 上,而应用到虚拟 DOM 上。最后一次性的应用到 DOM 上。
- 使用
webworker解决程序阻塞问题 IntersectionObserver
js
const observer = new IntersectionObserver(function (changes) {
changes.forEach(function (element, index) {
if (element.intersectionRatio > 0) {
observer.unobserve(element.target);
element.target.src = element.target.dataset.src;
}
});
});
function initObserver() {
const listItems = document.querySelectorAll("img");
listItems.forEach(function (item) {
observer.observe(item);
});
}
initObserver();- 虚拟滚动
vertual-scroll-list requestAnimationFrame、requestIdleCallback

- 尽量避免使用
eval, 消耗时间久 - 使用事件委托,减少事件绑定个数。
- 尽量使用 canvas 动画、
CSS动画
(7)字体优化
css
@font-face {
font-family: "Bmy";
src: url("./HelloQuincy.ttf");
font-display: block;
/* block 3s 内不显示, 如果没加载完毕用默认的 */
/* swap 显示老字体 在替换 */
/* fallback 缩短不显示时间, 如果没加载完毕用默认的 ,和block类似*/
/* optional 替换可能用字体 可能不替换*/
}
body {
font-family: "Bmy";
}FOUT(Flash Of Unstyled Text) 等待一段时间,如果没加载完成,先显示默认。加载后再进行切换。
FOIT(Flash Of Invisible Text)字体加载完毕后显示,加载超时降级系统字体 (白屏)
4、优化策略
- 关键资源个数越多,首次页面加载时间就会越长
- 关键资源的大小,内容越小,下载时间越短
- 优化白屏:内联
css和内联js移除文件下载,较小文件体积 - 预渲染,打包时进行预渲染
- 使用
SSR加速首屏加载(耗费服务端资源),有利于SEO优化。 首屏利用服务端渲染,后续交互采用客户端渲染
5、浏览器的存储
cookie: cookie 过期时间内一直有效,存储大小4k左右、同时限制字段个数,不适合大量的数据存储,每次请求会携带cookie,主要可以利用做身份检查。- 设置
cookie有效期 - 根据不同子域划分
cookie较少传输 - 静态资源域名和
cookie域名采用不同域名,避免静态资源访问时携带cookie
- 设置
localStorage: chrome 下最大存储5M, 除非手动清除,否则一直存在。利用localStorage存储静态资源jsfunction cacheFile(url) { let fileContent = localStorage.getItem(url); if (fileContent) { eval(fileContent); } else { let xhr = new XMLHttpRequest(); xhr.open("GET", url, true); xhr.onload = function () { let reponseText = xhr.responseText; eval(reponseText); localStorage.setItem(url, reponseText); }; xhr.send(); } } cacheFile("/index.js");sessionStorage: 会话级别存储,可用于页面间的传值indexDB:浏览器的本地数据库 (基本无上限)jslet request = window.indexedDB.open("myDatabase"); request.onsuccess = function (event) { let db = event.target.result; let ts = db.transaction(["student"], "readwrite"); ts.objectStore("student").add({ name: "zf" }); let r = ts.objectStore("student").get(5); r.onsuccess = function (e) { console.log(e.target.result); }; }; request.onupgradeneeded = function (event) { let db = event.target.result; if (!db.objectStoreNames.contains("student")) { let store = db.createObjectStore("student", { autoIncrement: true }); } };
6、增加体验 PWA(Progressive Web App)
webapp用户体验差(不能离线访问),用户粘性低(无法保存入口),pwa就是为了解决这一系列问题,让webapp具有快速,可靠,安全等特点
Web App Manifest:将网站添加到桌面、更类似 native 的体验Service Worker:离线缓存内容,配合cache APIPush Api&Notification Api: 消息推送与提醒App Shell&App SkeletonApp壳、骨架屏
7、LightHouse使用
sh
npm install lighthouse -g
lighthouse http://www.taobao.com可以根据 lighthouse 中的建议进行页面的优化
requestFrameAnimation requestAdleCallback
图片 contain