Skip to content

HTML

HTML 文档

HTML(HyperText Markup Language,超文本标记语言)是用于描述网页结构的标准标记语言,通过各种标签标记文本、图像、链接等内容,使浏览器能正确解析并显示网页。

一个标准的 HTML 文档通常包含以下部分:

  • <!DOCTYPE html>:声明文档类型,告知浏览器使用 HTML5 标准解析页面。
  • <html>:整个文档的根元素。
  • <head>:存放文档的元数据(meta 信息)、标题、样式、外部链接等。
  • <body>:包含页面的主要内容,如文本、图片、链接等。

行内元素与块级元素

属性行内元素块级元素
占据空间仅限于标签边框内占满父元素宽度
排列方式同行排列,不换行独占一行
包含内容文本和行内元素行内元素及其他块级元素
盒模型width/height 无效,上下边距无连带影响完全支持 widthheight 及边距
常见标签aspanimgbuttoninputdivph1~h6

HTML5 新特性

  • 语义化标签:新增 <header><footer><article><nav> 等标签,使文档结构更清晰。

  • 增强的表单:扩展 <input>type 属性(如日期、时间、邮箱等),并增加 <datalist>, <keygen>, <output> 等元素。

  • 多媒体支持:通过 <audio><video> 标签以及相应 API 轻松嵌入和控制音视频。

  • Canvas 绘图<canvas> 提供了用 JavaScript 绘制图形、动画和图像的能力。

  • 地理定位 API:利用 Geolocation API 获取用户地理位置信息,方便实现定位功能。

  • Web 存储:使用 localStoragesessionStorage 在客户端保存数据,减少服务器通信。

  • WebSocket:支持基于 TCP 的全双工通信,实现实时数据交换。

  • Web Workers:后台多线程执行 JavaScript,提升页面响应效率。

  • 离线应用与缓存:利用 Application Cache 缓存资源,实现离线访问网页。

语义化标签

语义化标签指那些通过名称能够准确描述其内容含义的标签。

例如:

  • <header> 表示页面或区域的页眉;
  • <nav> 表示导航部分;
  • <article> 用于独立的文章内容;
  • <footer> 表示页脚。

作用:

  • 使页面内容结构清晰
  • 提高代码可读性
  • 方便搜索引擎理解页面结构,利于 SEO。

浏览器及其内核理解

浏览器的主要功能是 呈现 Web 资源,它通过 URI(统一资源标识符) 定位资源,从服务器请求并在窗口中显示内容,如 HTML、CSS、图片或 PDF 等格式。

浏览器由两部分组成:

  1. Shell(外壳): 负责用户界面,如菜单、工具栏和设置等,调用内核实现功能。
  2. 内核(核心): 主要负责网页的解析与渲染。

浏览器内核包含两个核心模块:

  • 渲染引擎(Rendering Engine): 解析 HTML、CSS 并渲染页面内容。
  • JS 引擎(JavaScript Engine): 解析和执行 JavaScript,赋予网页动态交互能力。

早期渲染引擎和 JS 引擎并未明确区分,随着 JS 引擎的独立发展,"浏览器内核" 现多指 渲染引擎。不同浏览器厂商对 Web 规范的实现有所差异,导致兼容性问题。

浏览器的渲染原理

  1. 资源获取:根据 URL 下载 HTML、CSS、JS、图片等资源。
  2. 构建 DOM 和 CSSOM:分别解析 HTML 和 CSS,构建 DOM 树和 CSSOM 树。
  3. 生成渲染树:将 DOM 树和 CSSOM 树合并,仅保留需显示的节点,形成渲染树。
  4. 布局:根据渲染树计算每个元素的确切位置和大小。
  5. 绘制:将各元素转换成像素,在屏幕上绘制出页面内容。

浏览器的渲染过程是逐步完成的,为了更好的用户体验,渲染引擎将会尽可能早的将内容现呈到屏幕上,解析完一部分内容就显示一部分内容

渲染过程中遇到 JS 文件怎么处理

JavaScript 的加载、解析与执行会阻塞文档的解析,在构建 DOM 树时,HTML 解析器若遇到了 JavaScript,那么它会暂停文档的解析,将控制权移交给 JS 引擎,等 JS 引擎运行完毕,浏览器再从中断的地方恢复继续解析文档。

如果想首屏渲染得越快,就不应该在首屏加载 JS 文件,这也是建议将 script 标签放在 body 标签底部的原因。或者可以给 script 标签添加 defer 或者 async 属性。

asyncdefer 的作用和区别

两者都是用来告诉浏览器异步加载 JavaScript 脚本,从而避免阻塞页面的 HTML 解析,提升页面加载速度。

  • 使用 async 的 JS 脚本在下载后立即执行(无序),适合独立、互不依赖的脚本,例如统计、广告等
  • 使用 defer 的 JS 脚本则在文档解析完毕后按顺序执行,适合依赖 DOM 或相互之间有依赖关系的脚本。

JS 延迟加载的方式

  • 将脚本放在页面底部:将 <script> 标签放在 </body> 前,确保页面内容先行加载。
  • defer 属性:在 <script> 标签中添加 defer 属性,脚本会在 HTML 解析完毕后按顺序执行。
  • async 属性:在 <script> 标签中添加 async 属性,脚本异步加载,加载完成后立即执行,执行顺序不确定。
  • 动态创建脚本:使用 JavaScript 动态创建并插入 <script> 标签,实现按需加载。
  • 使用 setTimeout 方法:通过 setTimeout() 延迟执行脚本,给页面其他资源留出加载时间。

重绘和重排(回流)

  • 重绘:当元素的 外观样式(如颜色、背景) 发生变化,但不影响布局时,浏览器会重新绘制元素的外观,这个过程称为重绘。

    常见会引起重绘的属性和方法:

    • 颜色属性:color 文本颜色、background-color 背景颜色
    • 背景属性:background-image 背景图片
    • 边框属性:border 边框样式、宽度、颜色
    • 文本属性:font-size 字体大小、font-family 字体、font-weight 字体粗细、text-decoration 文本装饰
    • 显示属性:display 元素的显示方式(例如,从 noneblock
    • 定位属性:position: 元素定位方式(例如,从 staticrelativeabsolute
    • ...
  • 重排(回流):当 DOM 元素的几何属性(如位置、大小)发生变化时,浏览器需要重新计算布局,这个过程称为重排。

    常见引起重排(回流)的属性和方法:

    • 添加或者删除可见的 DOM 元素。
    • 元素尺寸改变(边距、填充、边框、宽度和高度)。
    • 内容变化,比如用户在 input 框中输入文字。
    • 浏览器窗口尺寸改变 resize 事件发生时。
    • ...

重排必然会导致重绘,但重绘不一定需要重排。因此,尽量减少不必要的重排和重绘,有助于提升网页的渲染性能。

如何减少重绘和重排

  • 批量修改样式:避免逐一修改样式属性,通过修改 className 一次性更改多个样式。

  • 使用文档碎片:当需要在 DOM 中插入大量节点时,使用文档碎片创建和操作节点,然后再一次性插入到 DOM 中,减少重排的次数。

  • 脱离文档流:对于需要频繁操作的元素,可以使用 position: absoluteposition: fixed 使其脱离文档流,减少对其他元素布局的影响。

  • 避免频繁访问布局信息:多次读取布局属性(如 offsetTopclientWidth)会触发重排,建议将其值缓存到局部变量中,减少重复访问。

  • 使用 Flexbox 和 Grid 布局:使用 Flexbox 和 Grid 布局可以减少元素的重绘和重排,因为它们不会像传统布局模型那样频繁引起元素的重新排列。

  • 节流和防抖:在处理用户输入、滚动等事件时,可以使用节流(throttle)和防抖(debounce)的技术,减少频繁的重排和重绘操作。

DOMContentLoaded 事件和 Load 事件

事件触发时机适用场景
DOMContentLoadedHTML 解析完毕(不等图片、CSS 加载)DOM 操作,初始化 JS 逻辑
Load页面所有资源加载完成(包括图片等)资源相关的操作,如动画、布局调整
  • 仅需操作 DOM,使用 DOMContentLoaded,避免等待不必要的资源加载。
  • 依赖页面所有资源,如图片尺寸计算,则使用 load

浏览器端的存储技术

浏览器端的常用存储技术有 Cookies、LocalStorage、SessionStorage、IndexedDB 和 Cache API 等。

存储方式容量过期机制特点
Cookies4KB可设过期时间,每次请求都会携带适合存小量数据,不安全,不适合存敏感信息
LocalStorage5MB永久保存,需手动清除适合持久存储,简单易用,受同源策略限制
SessionStorage5MB关闭页面即清除适合临时存储,生命周期随会话结束
IndexedDB几百 MB+需手动管理适合存大量数据,支持异步和事务机制
Cache API依浏览器而定需手动管理适合缓存网络资源,支持离线访问

浏览器内多个标签页之间的通信

实现多个标签页之间的通信,本质上都是通过中介者模式来实现的。因为标签页之间没有办法直接通信,因此我们可以找一个中介者,让标签页和中介者进行通信,然后让这个中介者来进行消息的转发。

  1. 使用 localStoragesessionStorage
    这两个 Web Storage 技术可以在同一域下的不同标签页之间共享数据。当一个标签页修改 localStoragesessionStorage 中的数据时,其他标签页可以通过监听 storage 事件来得知数据的变化。

    javascript
    // 在页面 1 中设置数据
    localStorage.setItem('key', 'value');
    
    // 在页面 2 中监听 storage 事件,当页面 1 修改数据时会触发
    window.addEventListener('storage', function(event) {
      if (event.key === 'key') {
        var updatedValue = event.newValue;
        // 处理更新后的数据
      }
    });
  2. 使用 Broadcast Channel API
    BroadcastChannel API 提供了一种在不同窗口或标签页之间进行广播通信的方式。不同窗口可以通过同一个 BroadcastChannel 实例进行通信。

    javascript
    // 在页面 1 中创建广播通道
    const channel = new BroadcastChannel('my_channel');
    
    // 在页面 2 中监听消息
    channel.addEventListener('message', function(event) {
      var receivedData = event.data;
      // 处理接收到的数据
    });
    
    // 在页面 1 中发送消息
    channel.postMessage({ key: 'value' });
  3. 使用 SharedWorker
    SharedWorker 是一种在不同标签页之间共享状态的方式,不同于普通的 Web Worker,SharedWorker 可以被多个窗口共享。通过 postMessage 方法在不同标签页之间发送消息。

    javascript
    // 在页面 1 中创建 SharedWorker
    const worker = new SharedWorker('worker.js');
    
    // 在页面 2 中监听消息
    worker.port.addEventListener('message', function(event) {
      var receivedData = event.data;
      // 处理接收到的数据
    });
    
    // 在页面 1 中发送消息
    worker.port.postMessage({ key: 'value' });
  4. 使用 WebSocket
    WebSocket 协议可以实现服务器推送,服务器就可以用来当做这个中介者。标签页通过向服务器发送数据,然后由服务器向其他标签页推送转发。

Canvas 和 SVG

特性CanvasSVG
渲染方式逐像素绘制(位图)基于 XML(矢量图)
缩放效果可能失真(像素化)不失真,保持清晰
交互性需要手动处理事件直接支持 DOM 事件
适合场景大量动态绘制,如游戏、数据可视化复杂矢量图形,如图标、地图
  • Canvas:适合高性能、频繁更新的图形,如动画、游戏、实时图表。
  • SVG:适合静态或少量动态的矢量图,如图标、地图、流程图。

渐进增强和优雅降级

  • 渐进增强:针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。

  • 优雅降级:一开始就根据高版本浏览器构建完整的功能,然后再针对低版本浏览器进行兼容。

浏览器地址栏输入 URL 到页面渲染的整个流程

  1. URL 解析:浏览器会对该 URL 进行解析,分析需要使用的传输协议请求资源的路径

  2. 缓存检查:检查本地缓存,如果存在缓存资源且未过期则直接使用,否则发起新请求。

  3. DNS 查询:浏览器通过 DNS 解析器查询该域名对应的 IP 地址。如果 DNS 缓存中存在该域名对应的 IP 地址,则直接返回;否则,将请求发送到 DNS 服务器进行解析。

  4. 建立 TCP 连接:浏览器使用 HTTP 协议建立与服务器三次握手的 TCP 连接。在建立连接的过程中,如果是 HTTPS 协议,还需要进行 TLS/SSL 四次握手来确保通信安全。

  5. 发起 HTTP 请求:浏览器向服务器发送 HTTP 请求。

  6. 服务器处理请求:服务器接收到 HTTP 请求后,根据请求的 URL 和方法进行相应的处理。处理过程可能包括查询数据库、生成动态内容、读取静态文件等操作。

  7. 服务器响应:服务器处理完请求后,将相应的结果以 HTTP 响应的形式返回给浏览器。

  8. 接收响应:浏览器接收到服务器的响应后,开始解析响应。检查响应头中的 Content-Type,确定响应的数据类型(如 HTML、JSON、图片等),然后根据相应的数据类型进行相应的处理。

  9. 页面渲染:如果响应的是 HTML 类型的数据,浏览器开始解析 HTML,并构建 DOM 树。在构建 DOM 树的过程中,遇到外部资源(如 CSS、JavaScript、图片等)的引用,则会发起额外的请求获取这些资源。同时,浏览器还会解析 CSS,构建 CSSOM 树,并将 DOM 树和 CSSOM 树合并成渲染树。最后,浏览器根据渲染树进行页面渲染,呈现给用户。

  10. 断开连接:页面加载完成后,通过 TCP 四次挥手断开连接。

前端性能优化

前端性能优化是提高网页加载速度和用户体验的关键。需要根据项目的实际情况做相对应的优化,以下是一些常见的前端性能优化方案:

  1. 资源优化

    • 文件优化(多个文件合并为一个,JS/CSS 代码合并、压缩、拆分、按需加载、懒加载、预加载、异步加载)
    • 图片优化 (选择适当的格式,如:WebP/AVIF/SVG、压缩、懒加载、预加载、雪碧图、base64)
    • 图标优化 (iconify 按需加载)
    • Tree-shaking 减小包体积
    • 缓存优化(浏览器缓存,对常用不变的资源进行缓存、本地缓存,如:LocalStorage、SessionStorage、IndexedDB)
  2. 渲染优化

    • 减少 DOM 操作,避免重绘和重排
    • 使用虚拟滚动和分页
    • 骨架屏和占位 UI
    • 优先显示关键内容
    • 使用请求动画帧(requestAnimationFrame)
  3. 网络优化

    • HTTP/2 和 HTTP/3(减少网络请求的开销)
    • 资源压缩 (Gzip/Brotli)
    • CDN 加速
    • 预连接 (preconnect)、预加载 (preload) 和预获取 (prefetch)
    • 懒加载和按需加载
    • 缓存策略
    • DNS 优化(DNS 预解析、DNS 缓存)
  4. 运行时优化

    • Web Workers(处理密集计算和耗时长的任务,避免阻塞主线程)
    • 防抖和节流
    • 事件委托
    • 编译优化 (AOT 编译)
  5. 服务端优化

    • 服务端使用 SSR(提前生成 HTML,减轻客户端渲染的负担)
    • 服务端预渲染(预渲染关键页面,提高首屏加载速度)
    • 响应资源压缩(接口响应启用 Gzip 等方式对传输的资源进行压缩)

这些优化方案是综合应用的结果,不同的项目和场景需要结合不同的优化策略

Released under the AGPL-3.0 License