从输入url到页面渲染的每一步以及优化

85 阅读2分钟

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等等