本文仅论述优化的手段,不涉及执行这些操作的根因,后续空闲时在整理“为什么”。
指标有很多,比如 lighthouse 中使用的指标有 FCP、LCP、TBT、CLS、Speed Index,这些是最终的性能评估指标。
性能优化方案落地时,主要参看的指标:
指标 | 名词解释 | 描述 |
---|---|---|
DCL [DOMContentLoaded] | DOM 解析结束时间 | HTML 文档被解析成 DOM 树并且所有的标签都已经可用,但是外部资源(如图像、样式表等)可能还没有加载完成。 |
FP [First Pain] | 首次绘制 | 浏览器首次将像素渲染到屏幕上的时间点,即页面第一次有可见的内容呈现给用户。 |
FCP [First Content Pain] | 首次内容绘制 | 浏览器首次将第一个有意义的内容(如文本、图像、SVG 等)呈现到屏幕上的时间点。 |
LOAD | 加载结束时间 | 在整个页面及其所有资源(包括图像、样式表、脚本等)加载完成后触发。 |
通过 Chrome 的 Performance 面板,可以看到大部分的值,这里说下如何通过 API 获取值。
1.1 DCL
console.time("DCL");
document.addEventListener("DOMContentLoaded", function (event) {
console.timeEnd("DCL");
});
1.2 FP 与 FCP
const [fp, fcp] = performance.getEntriesByType("paint");
const fpDuration = fp.startTime;
const fcpDuration = fcp.startTime;
1.3 Load
const entry = performance.getEntries()[0];
const loadDuration = entry.duration;
针对静态资源保持一个大体的优化思路,即在当前优先处理与当前页面相关的资源。
下载过程中没有相关的处理
一个复杂项目中可能会加载很多的 css 样式表,有些样式表不一定会被使用到,可以将这部分的样式去除。相关工具:
针对变换、动画等场景,可以启用 GPU 渲染。方式:
避免@import,其弊端:
压缩资源
,将多余的换行符、多余的打印等去除;
丑化资源
,将代码中变量名、函数名等替换为简短的、难以阅读的代码。
当个 JS 文件交大时,尝试执行分包处理。主流的构建工具都包含对应的处理方式:
有段时间,雪碧图是一个很流行的图标整合方式。到了现在这个阶段,字体图标是一个更好的方案。比如:阿里字体图
常用的图片格式有 png、jpg、svg、webp。图片可以按照多个维度进行划分,如下:
WebP
有 google 开发,旨在提供更高的压缩率和更高的图像质量,以替代传统的 JPEG、PNG 和 GIF 格式。WebP
格式的特性:
推荐使用WebP
格式,主流浏览器厂商都已支持。
为了保险起见,可以采用标签的回退语法确保正常显示。
<picture>
<source srcset="image.webp" type="image/webp" />
<source srcset="image.jpg" type="image/jpeg" />
<img src="image.jpg" alt="图像" />
picture>
预加载分为几种类型,如:
浏览器在用户浏览页面时,在后台运行 DNS 的解析
<link rel="dns-prefetch" href="//fonts.googleapis.com" />
允许浏览器在一个 HTTP 请求正式发给服务器前预先执行一些操作,这包括 DNS 解析,TLS 协商,TCP 握手,这消除了往返延迟并为用户节省了时间。
<link href="https://cdn.domain.com" rel="preconnect" crossorigin />
在浏览器空闲时,加载站点将来可能用到的资源。
<link rel="prefetch" href="/uploads/images/pic.png" />
<link rel="preload" href="styles.css" as="style" />
<link rel="preload" href="jQuery.js" as="javascript" />
当资源出现在可视区时,再加载资源。实现方式,基于IntersectionObserve
+ src 替换
的思路实现。
现代工程,大多是 SPA 工程,路由是有前端控制,当路由变化时再加载对应的资源很有必要。
const Home = () => import("./components/Home.vue");
const About = () => import("./components/About.vue");
const routes = [
{ path: "/", component: Home },
{ path: "/about", component: About },
];
const router = new VueRouter({
routes,
});
const Home = React.lazy(() => import("./components/Home"));
const About = React.lazy(() => import("./components/About"));
function App() {
return (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
</Switch>
</Suspense>
</Router>
);
}
export default App;
启用 CDN 网络,减少资源的加载时长。比如:腾讯桶
请求传输的压缩算法,常用的有:
备注:
存在无损的 PNG 资源时,不要启用 GZIP。否则会起到反效果,导致压缩后的文件更大
升级为 HTTP/2,好处:
性能优化,名词高大上,真正落地时会发现都是些基本功。
方法很简单,重要的是要知道为什么要这么做,空闲时再聊这块。