前端性能优化方向
- 减少网络加载耗时
- 减少 CPU 计算量
都可以考虑用空间换时间
让加载更快
减少资源体积
清理冗余的代码、图片和视频等无效资源
优化代码结构
将重复的代码提炼为公共组件、公共样式、全局变量和函数等。
打包构建时,将代码和资源进行压缩
减少访问服务器的次数
合并代码,减少代码文件数量
使用 SSR 服务器端渲染
将网页和数据一起加载,一起渲染,如早先的 JSP ASP PHP,现在的 vue React SSR
非 SSR(前后端分离) : 先加载网页,再加载数据,再渲染数据
以 webpack 打包构建的 hash 命名机制为例:
- 静态资源加 hash 后缀,根据文件内容计算 hash
- 文件内容不变,则 hash 不变,则 ur 不变
- ur 和文件不变,则会自动触发 http 缓存机制,返回 304
使用更快的网络
使用 CDN 加载静态资源(通用的 js ,css 文件,图片,视频等)
让渲染更快
CSS 放在 head 里
<head> <meta charset="UTF-8"> <title>网页标题</title> <!-- 引入外部 CSS 文件 --> <link rel="stylesheet" href="styles.css"> <!-- 内联 CSS 样式 --> <style> body { background-color: #f1f1f1; font-family: Arial, sans-serif; } h1 { color: blue; } </style> </head>
Js 放在 body 最下面
<body> <!-- 此处省略了其他HTML内容 --> <!-- 将JavaScript代码放置在body标签的最后部分 --> <script src="your_js_file.js"></script> </body>
尽早执行JS,用DOMContentLoaded 触发
window.addEventListener("load", function () { // 页面的全部资源加载完才会执行,包括图片视频等 }); document.addEventListener("DOMContentLoaded", function () { // DOM 渲染完即可执行,此时图片、视频可能还没有加载完 });
使用懒加载
监听页面的滚动,当资源(如图片/视频)即将进入视口(用户可见的网页区域)时,再加载资源。
具体实现方法可参考
缓存DOM 查询
频繁的DOM 操作,合并到一起插入 DOM 结构
节流 throttle
含义:节省流量,即减少高频事件内操作的执行频率。
目标:让高频事件内的操作,按预期的频率触发
功效场景:
- 拖拽元素时,避免 drag 事件内的操作过于频繁的执行
原理:见下图
代码 : 需能手写
// 节流 function throttle(fn, delay = 100) { let timer = null return function () { if (timer) { return } timer = setTimeout(() => { fn.apply(this, arguments) timer = null }, delay) } }
使用
const div1 = document.getElementById('div1') div1.addEventListener('drag', throttle(function (e) { console.log(e.offsetX, e.offsetY) }))
防抖 debounce
含义:防止抖动,即防止高频事件内的操作重复触发
目标:让高频事件内的操作等待高频事件结束时触发一次
功效:降低了高频事件内操作的频率,避免了性能的浪费,有效降低页面卡顿的风险。
场景:
- 监听用户输入,实时搜索(如百度搜索),用防抖来等待用户停止输入时,执行一次查询操作。
- 不断地调整浏览器窗口大小会不断的触发 window 的 resize 事件,用防抖来等待用户停止调整浏览器窗口大小时,执行一次 resize 事件内的操作。
原理:见下图
代码 : 需能手写
// 防抖 function debounce(fn, delay = 500) { // timer 是闭包中的 let timer = null return function () { if (timer) { clearTimeout(timer) } timer = setTimeout(() => { fn.apply(this, arguments) timer = null }, delay) } }
使用
const input1 = document.getElementById('input1') input1.addEventListener('keyup', debounce(function (e) { console.log(input1.value) }, 600))
选择性能更优的页面渲染方案
动画渲染
- 需实时更新的动画,使用 RAF
- 简单的静态或者中等复杂度的动画,用 CSS
- 若使用的 setTimeout 实现的动画,建议改用 CSS 或 RAF 进行优化!
js 实现动画的两种方案对比:setTimeout vs RAF