1.输入url,dns解析出ip地址
优化方向1: dns预解析
将后续可能用到的域名解析为ip地址,并缓存至系统,因为每次dns解析都是先逐步查看缓存再去服务器查找,所以可以提前从缓存中拿到ip地址,后续的解析步骤也就不用再执行了。
<link rel="dns-prefetch" href="//baidu.com" / >
// dns-prefetch.js
const fs = require('fs')
const path = require('path')
const { parse } = require('node-html-parser')
const { glob } = require('glob')
const urlRegex = require('url-regex')
// 获取外部链接的正则表达式
const urlPattern = /(https?:\/\/[^/]*)/i
const urls = new Set()
// 遍历dist目录中的所有HTML、JS、CSS文件
async function searchDomin() {
const files = await glob('dist/**/*.{html,css,js}')
for (const file of files) {
const source = fs.readFileSync(file, 'utf-8')
const matches = source.match(urlRegex({ strict: true }))
if (matches) {
matches.forEach((url) => {
const match = url.match(urlPattern)
if (match && match[1]) {
urls.add(match[1])
}
})
}
}
}
// 在index.html文件<head>标签中插入link标签
async function insertLinks() {
const files = await glob('dist/**/*.html')
const links = [...urls].map((url) => `<link rel="dns-prefetch" href="${url}" />`).join('\n')
for (const file of files) {
const html = fs.readFileSync(file, 'utf-8')
const root = parse(html)
const head = root.querySelector('head')
head.insertAdjacentHTML('afterbegin', links)
fs.writeFileSync(file, root.toString())
}
}
async function main() {
await searchDomin()
await insertLinks()
}
main()
2.请求资源
优化方向1: cdn(内容分发网络)
将资源部署在距离更近的服务器上,如阿里云等,避免网络拥挤
3.响应请求发送数据
优化方向1: 减小资源体积
使用treeShaking删除无用代码
生产环境不使用sourcemap
优化方向2: 提前&延后加载数据
prefetch
离线包
preload
懒加载
路由懒加载,图片懒加载等等
4.生成dom树
优化方向1: 避免一次性生成全部(过多)dom节点
虚拟列表
优化方向2: 骨架屏
优化用户体验,实际并未缩短时长
优化方向3: webworker
gui线程与js线程是互斥的,因此如果js上存在长任务就会阻塞渲染,此时我们可以使用webworker,Web Worker就是一个运行在后台的JavaScript线程,不会影响页面的响应,我们将长任务交给webworker去执行,监听到执行完成后调用结果即可。
4.生成css树
优化方向1: 将css写在header中,提前解析
优化方向2: 优化CSS编码风格,尽可能减少重排重绘
-
元素显隐操作频繁,可设置 visibility: hidden,让元素占位不变,不会触发重排,仅触发重绘
-
已知图片的宽高,样式可先设置width、height,避免图片下载后整个页面发生重排
-
避免使用CSS表达式
-
避免频繁设置同一div样式,可进行一次性更改
-
动画使用绝对定位(脱离文档流)定位,避免触发重排
-
一次性改变margin/padding,避免多次写margin-left,right等等