从浏览器输入网址到网页被渲染出来的过程: 当你在浏览器地址栏输入一个网址并按下回车键后,整个网页从请求到渲染的过程可以分为以下几个步骤:
1. DNS 解析
- 目的:将你输入的域名(如
www.example.com)解析成一个具体的 IP 地址(如192.0.2.1),因为网络通信依赖 IP 地址。 - 过程:
- 浏览器会首先检查缓存(浏览器缓存、本地缓存、系统缓存)中是否有该域名的解析记录。
- 如果缓存没有找到,则会向 DNS 服务器发送查询请求,逐级解析直到获得对应的 IP 地址。
- 最终,DNS 解析返回一个目标服务器的 IP 地址。
2. 建立 TCP 连接
- 目的:通过网络与目标服务器建立通信通道。
- 过程:使用 TCP/IP 协议,浏览器与目标服务器之间通过三次握手建立连接:
- 客户端发送 SYN:浏览器向服务器发送请求建立连接的信号(SYN)。
- 服务器响应 SYN-ACK:服务器接收到 SYN 后,确认可以建立连接,并返回 SYN-ACK。
- 客户端发送 ACK:客户端确认连接,发送 ACK,连接建立完成。
如果是 HTTPS 请求,还会在此基础上进行 TLS/SSL 握手,用于建立加密通信。
3. 浏览器发送 HTTP 请求
- 目的:向目标服务器请求网页资源。
- 过程:
- 浏览器根据用户输入的网址构造一个 HTTP 请求报文,内容包括:
- 请求方法(GET、POST 等)。
- URL 路径(如
/index.html)。 - 请求头(包含浏览器类型、支持的格式等信息)。
- 报文通过已建立的 TCP 通道发送到目标服务器。
- 浏览器根据用户输入的网址构造一个 HTTP 请求报文,内容包括:
4. 服务器处理请求并返回响应
- 目的:服务器接收并处理请求,返回网页内容。
- 过程:
- 服务器接收浏览器的请求,根据 URL 路径定位到对应的资源(如 HTML 文件)。
- 如果资源是动态内容(如使用 PHP、Node.js 等生成的页面),服务器会运行后端代码生成 HTML 内容。
- 服务器构造 HTTP 响应报文,包括:
- 响应状态码(如 200、404)。
- 响应头(如内容类型、缓存指令)。
- 响应体(如 HTML 文件)。
- 服务器将响应报文通过 TCP 通道发回给浏览器。
5. 浏览器解析和渲染网页
- 目的:将服务器返回的 HTML 文件和相关资源(CSS、JS、图片等)加载并渲染成可视化的网页。
- 过程:
-
HTML 解析:
- 浏览器从响应体中读取 HTML 内容,开始构建 DOM 树。
- 如果遇到外部资源(如 CSS、JavaScript、图片等),会发送新的请求获取这些资源。
-
CSS 解析:
- 下载并解析 CSS 文件,构建 CSSOM 树。
- 与 DOM 树结合形成 渲染树。
-
JavaScript 执行:
- 下载并执行 JavaScript 文件。
- 可能会修改 DOM 或 CSSOM,触发重新渲染。
-
渲染树布局和绘制:
- 布局(Layout):根据渲染树计算每个元素的位置和大小。
- 绘制(Painting):将布局结果绘制到屏幕上。
-
6. 用户与网页交互
- 网页完全渲染后,用户可以与页面内容交互(如点击按钮、填写表单等)。
- 用户的操作可能触发 JavaScript 事件,从而引起 DOM 的变化或向服务器发送新的请求。
整体流程图
1. 输入网址
↓
2. DNS 解析
↓
3. 建立 TCP 连接(三次握手)
↓
4. 发送 HTTP/HTTPS 请求
↓
5. 服务器返回响应
↓
6. 浏览器解析和渲染(HTML、CSS、JS)
↓
7. 网页展示并交互
涉及的核心技术
- DNS(域名解析系统):负责将域名翻译为 IP 地址。
- HTTP/HTTPS:负责客户端与服务器之间的数据通信。
- TCP/IP:传输层和网络层协议,确保数据可靠传输。
- 浏览器渲染引擎:负责将 HTML、CSS、JS 转换为页面。
常见的优化点
- DNS 缓存:减少域名解析的时间。
- CDN 加速:通过内容分发网络提供就近的资源加载。
- 压缩资源文件:通过 Gzip 或 Brotli 减小文件大小。
- 懒加载:延迟加载图片或其他资源,提高页面加载速度。
- HTTP/2:支持多路复用,减少请求阻塞。
懒加载(Lazy Loading)是一种优化资源加载和使用的技术,指的是当页面或应用加载时,只加载当前需要的资源,将其他资源的加载延迟到真正需要的时候(如用户滚动到某个位置时)。它的主要目的是提升首屏加载速度和减少不必要的资源消耗。
懒加载的核心概念
- 普通加载:页面加载时会一次性加载所有资源(图片、脚本、数据等),即使某些资源并不立即需要。
- 懒加载:页面加载时只加载必要的资源,其他资源延后加载,比如等到用户实际需要时(如滚动到可见区域)。
懒加载的应用场景
-
图片懒加载:
- 网页中大量图片时,只加载用户当前视口中可见的图片,其余图片在用户滚动到它们的可见范围时再加载。
- 示例:电商网站的产品列表、博客中的文章图片。
-
视频懒加载:
- 视频文件体积较大,懒加载可以只在用户点击播放或滚动到视频可见区域时才开始加载。
- 示例:新闻网站的视频内容。
-
数据懒加载(分页加载):
- 页面只加载当前的分页数据,当用户滚动到页面底部时再加载下一页的数据。
- 示例:社交媒体的无限滚动、商品列表的分页加载。
-
组件懒加载(前端框架):
- 在单页应用(SPA)中,某些页面或功能模块用到的代码并不需要在初次加载时全部加载,可以将它们延迟到用户访问对应页面时才加载。
- 示例:React 的动态
import、Vue 的异步组件。
图片懒加载的实现方法
1. 使用 HTML 原生属性
现代浏览器支持 <img> 的 loading="lazy" 属性,简单方便:
<img src="example.jpg" alt="Example" loading="lazy">
loading="lazy"会让图片仅在用户滚动到图片的可见区域时加载。
2. 使用 JavaScript 实现懒加载
通过监听页面的滚动事件,判断图片是否进入视口,进入视口后再加载。
传统实现(Intersection Observer API)
document.addEventListener("DOMContentLoaded", function () {
const lazyImages = document.querySelectorAll('img[data-src]');
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src; // 将真实图片地址赋值给 src
img.removeAttribute('data-src');
observer.unobserve(img);
}
});
});
lazyImages.forEach(img => observer.observe(img));
});
- 解释:
- 给图片设置一个
data-src属性来存放真实的图片地址,而src设置为占位图片或空。 - 使用
Intersection Observer检测图片是否进入视口(即是否可见)。 - 当图片进入视口时,将
data-src的值赋值给图片的src,从而加载真实图片。
- 给图片设置一个
3. 使用第三方库
有许多现成的懒加载库,封装好了各种功能,可以快速实现懒加载:
- LazyLoad.js
- Lazysizes
- Lozad.js
使用示例(以 Lazysizes 为例):
<img class="lazyload" data-src="example.jpg" alt="Example">
<script src="lazysizes.min.js"></script>
Lazysizes会自动处理data-src并进行懒加载。
懒加载的优势
- 提升首屏加载速度:
- 页面初始加载时只获取必要资源,减少页面加载时间。
- 减少带宽消耗:
- 用户未滚动到的内容不会加载,可以节省带宽,特别是对图片和视频等大资源。
- 提升用户体验:
- 用户可以更快看到关键内容,避免因为加载大量无关资源而卡顿。
懒加载的潜在问题
-
SEO 问题:
- 如果搜索引擎的爬虫不支持懒加载实现方式,可能会导致某些内容无法被索引(尤其是图片和异步加载的数据)。
- 解决办法:对重要内容使用服务端渲染(SSR)或预渲染工具(如 React 的
Next.js)。
-
不支持 JavaScript 的用户:
- 如果用户的浏览器禁用了 JavaScript,依赖 JS 实现的懒加载将失效。
- 解决办法:使用 HTML 原生的
loading="lazy"或设置合理的回退机制。
-
闪烁问题:
- 如果图片延迟加载,可能会导致页面在加载时内容发生跳动。
- 解决办法:设置图片的占位符或固定宽高避免布局抖动。