前言
性能优化的目的就是如何让页面加载的更快或者说如何让用户感觉到很快,当页面加载速度大于 300ms
,用户可以感知到白屏的存在;当页面加载速度大于 3000ms
,用户会觉得烦躁以及会关掉页面。所以性能优化在前端是非常重要!
那如何用户感觉到很快有很多的实现方案,比如说骨架屏,舒适的加载动画等等安抚用户情绪的产品设计。
而作为开发者来说,我们可以做哪些事情可以让页面真正的变得更快呢?
性能指标
我们需要查看一些指教,从而来决定我们是否应该去优化以及我们该从那些方向去优化,这很重要!
-
First Paint (FP)
首次绘制,从白屏到第一个像素点出现的时间。
-
First Content Paint (FCP)
首次内容绘制,网页首次绘制的内容的时间。
-
Speed Index
页面加载过程中的视觉显示速度。
-
Largest Contentful Paint (LCP)
最大的内容绘制完成的时间。
-
Total Blocking Time (TBT)
页面总阻塞的时间。
查看指标
-
Lighthouse
Lighthouse
是性能评测工具,支持移动端
和PC端
。
- Performance
window.performance.timing;
// PerformanceTiming{ ... }
Performance
接口可以获取到当前页面中性能相关的信息。
Performance.timing
返回 PerformanceTiming
对象,这个对象包含了页面相关的性能信息。
MDN Performance
https://developer.mozilla.org/zh-CN/docs/Web/API/PerformanceTiming
-
rollup-plugin-visualizer / webpack-bundle-analyzer
打包的时候生成可视化的依赖分析,分别基于
Rollup
和Webpack
。
如何优化
-
压缩代码
清除代码注释、空白字符和未使用的代码等等能够有效的减少
HTML 、CSS
和JavaScript
的前端加载的时间。 -
减少
HTTP
请求完整的
HTTP
请求需要经过三次握手的过程,HTTP
请求越多,相对应的花费的时间就越多。比如我们可以使用
CSS Sprites
或者Base64
来减少图片你的HTTP
请求。比如说我们使用
SSR
渲染加快首屏渲染。 -
压缩文件
通过
Gzip
来压缩HTML
、CSS
和JavaScript
文件能够有效的较少前端加载的时间。 -
延迟加载
页面优先展示视窗内可见区内的内容,延迟加载视窗内可见区外的内容。
-
CDN
加速CDN
优先为用户访问最近的CDN
节点,可以使用户更快的获取到资源。
实现思路
压缩代码
Vite
中默认开启了 Minify
,并且我们提供了 terser
和 esbuild
两种打包的方式。
默认为 esbuild
,它比 terser
快 20-40
倍,压缩率只差 1%-2%
。
但使用 terser
会被压缩的更小。
// vite.config.ts
export default defineConfig({
plugins: [vue()],
build: {
minify: "terser",
},
});
压缩文件
目前现代浏览器都支持 Gzip
对数据压缩和解压,开启 Gzip
压缩后极大的压缩文件大小,大大缩短了页面的加载时间。
// vite.config.ts
import viteCompression from "vite-plugin-compression";
export default defineConfig({
plugins: [vue(), viteCompression()],
});
webpack 中可以使用 compression-webpack-plugin 进行 Gzip 压缩文件的打包。
打包出 Gzip
压缩后需要在服务器开启 Gzip
压缩。
CDN 加速
无论是通过 Webpack
打包还是 Vite
打包,也会将我们使用的第三方的包进行打包,这样就进一步的提高了静态资源的体积,严重阻塞了页面的加载,白屏时间过长,给用户造成了非常不好的体验,那怎么样才可以解决这个问题呢?
在 Vite
中基于 Rollup
进行打包,同时我们也为我们提供了自定义 Rollup
的打包配置。
我们在打包的时候对第三方包进行移除,以达到减少 chunk
文件的体积的目的。
// vite.config.ts
export default defineConfig({
build: {
rollupOptions: {
external: ["vue", "vue-router", "naive-ui", "axios"],
},
},
});
移除了第三方包我们还需要通过 CDN
的方式引入依赖。
<!-- index.html -->
<script src="https://unpkg.com/vue@3.2.25/dist/vue.global.prod.js"></script>
<script src="https://unpkg.com/vue-router@4.0.0/dist/vue-router.global.prod.js"></script>
<script src="https://unpkg.com/naive-ui@2.30.5/dist/index.js"></script>
<script src="https://unpkg.com/axios@0.27.2/dist/axios.min.js"></script>
当然我们在开发模式下不需要引入依赖,我们可以使用 vite-plugin-html
插件动态的添加依赖。
// vite.config.ts
import { createHtmlPlugin } from "vite-plugin-html";
let cdn = {
js: [
"https://unpkg.com/vue@3.2.25/dist/vue.global.prod.js",
"https://unpkg.com/vue-router@4.0.0/dist/vue-router.global.prod.js",
"https://unpkg.com/naive-ui@2.30.5/dist/index.js",
"https://unpkg.com/axios@0.27.2/dist/axios.min.js",
],
};
export default ({ mode }) => {
// 非生产环境不引入cdn
if (mode === "development") {
cdn = {
js: [],
};
}
return defineConfig({
plugins: [
vue(),
createHtmlPlugin({
inject: {
data: {
injectScript: cdn.js,
},
},
}),
],
});
};
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title><%- title %></title>
<!-- 循环添加CDN -->
<% for (var i in injectScript) { %>
<script src="<%= injectScript[i] %>"></script>
<% } %>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
webpack 中可以使用 htmlWebpackPlugin 来实现。
虽然我们已经通过 CDN
的方式进行引入,但是我们代码内是通过 ESM
的方式进行引入的,而我们不可能手动的去修改整个项目中的所有依赖引入方式,所以我们需要使用 rollup-plugin-external-globals
插件用来构建全局依赖。
// vite.config.ts
import externalGlobals from "rollup-plugin-external-globals";
export default defineConfig({
build: {
rollupOptions: {
external: ["vue", "vue-router", "naive-ui", "axios"],
plugins: [
externalGlobals({
vue: "Vue",
"vue-router": "VueRouter",
"naive-ui": "naive",
axios: "axios",
}),
],
},
},
});
webpack 中为我们提供了 externals 来实现。
经过以上的操作,我们已经成功的将打包体积从 3.01MB
缩小到 6.78KB
。
总结
- 对第三方依赖不打包减少代码包的体积。
- 使用
CDN
加载静态资源。 - 使用
Gzip
压缩减少静态资源的体积。 - 减少
HTTP
请求,比如CSS Sprites
Base64
等。 - 提升用户体验感,让用户感觉变得更快。
最后
感谢你的阅读~
如果觉得这篇文章对你有所帮助,点赞、在看是最大的支持!