从输入url到界面展示发生了什么?

36 阅读3分钟

当我们访问url到界面渲染出来,整个流程是非常复杂的,主要是以下步骤:

  • url解析,判断是搜索的内容还是访问网站
  • 访问网站判断是否存在DNS缓存,如果没有缓存则解析DNS,获取IP
  • 进行http(s)连接,3次握手
  • 请求资源,通过content_type判断资源类型,如果是html文件,则网络进程,渲染进程开始启动
  • 解析html生成dom树,遇到css文件通过预解析线程进行下载和解析css文件,解析css文件完成后交给主渲染线程生成cssom树(浏览器的默认样式,自定义的样式都会在这里,确保每个属性都有值),遇到js文件会阻塞dom树解析,先下载并执行js文件。
  • 样式计算,遍历dom树,遍历每个节点,生成带有样式的dom树
  • layout,遍历dom树,获取每个节点的几何信息,例如宽高,相对位置等;dom树和布局树往往是不一致的,layout树会删除一些dispaly none的节点。生成layout的过程中一些新增一些匿名盒子,比如内容必须在行盒子内,行盒和块盒不能相邻。
  • 分层,浏览器会根据层叠上下文进行分层,防止每次变更整个界面全部更新
  • 绘制,生成绘制指令集(用于描述界面怎么画出来),然后交给合成线程
  • 分块,合成线程在线程池中取几个分块器线程一起帮忙,把每一层分成多个小块
  • 光栅化,分块完成后,每个块变成位图(这部分会用到gpu加速),优先处理窗口可视范围的块
  • 合成线程将位图信息交给gpu进程,再交给显卡来画界面

既然整个流程清楚了,那么涉及前端工程的一些优化也和上面这些步骤息息相关

  • dns预解析,dns-prefetch
  • http升级成https,增加最大并发请求数
  • 可以css放在顶部,先提供给用户一些loading页样式,正常script标签请求执行会阻塞html解析,可以js文件放在底部,或通过defer或者async优化
    • defer 请求异步进行,不会堵塞解析html,下载完成后等待dom解析完成再执行
    • async 请求会异步进行,不会堵塞解析html,等待下载完成后暂停dom解析,执行js
  • 充分利用浏览器缓存
  • 前端打包工具,压缩文件体积
    • JavaScript:UglifyPlugin
    • CSS :MiniCssExtractPlugin
    • HTML:HtmlWebpackPlugin
    • gzip:compression-webpack-plugin
  • 图片懒加载,或者改变图片格式webp
  • 减少回流,重绘。比如合成多次dom操作,将频繁操作的内容脱离文档流或者分层
  • js文件拆分,懒加载
  • 代码优化( if else 和 选择器)
  • web worker线程处理纯异步逻辑
  • css3的gpu加速,例如transform的本质是位图矩阵信息变化,发生在合成线程,所以效率高。