HTTP

HTTP 网络请求

HTTP �?Ajax 是前后端沟通的桥梁,面试重点考察,无论工作经验长短�?
::: tip
如有疑问,可免费 加群 讨论咨询,也可参�?1v1 面试咨询服务�?专业、系统、高效、全流程 准备前端面试
:::

TCP 是如何建立连接的,三次握手,四次挥手

参考答�?
::: details

三次握手

  • 客户端向服务端发送建立连接请求,客户端进�?SYN-SEND 状�?- 服务端收到建立连接请求后,向客户端发送一个应答,服务端进�?SYN-RECEIVED 状�?- 客户端接收到应答后,向服务端发送确认接收到应答,客户端进入 ESTABLISHED 状�?
    四次挥手

  • 客户端向服务端发送断开连接请求

  • 服务端收到断开连接请求后,告诉应用层去释放 tcp 连接

  • 服务端向客户端发送最后一个数据包 FINBIT ,服务端进入 LAST-ACK 状�?- 客户端收到服务端的断开连接请求后,向服务端确认应答

三次握手四次挥手,客户端都是主动方,服务端都是被动方。在状态方面:三次握手的客户端和服务端都是由原来的 closed 变为 established,四次挥手的客户端和服务端都是由原来�?established 变为 closed�?
:::

参考资�?
::: details

HTTP 几个版本的区�?

参考答�?
::: details

HTTP/0.9 - 单行协议

  • 只有 GET 请求行,无请求头和请求体
  • 只能传输 HTML 文件,以 ASCII 字符流返�?- 无响应头

HTTP/1.0 - 多类型支�?

  • 支持多种文件类型传输,不限于 ASCII 编码
  • 引入请求头和响应�? key-value 形式)
  • 每个请求都需要建立新�?TCP 连接

HTTP/1.1 - 持久连接

  • 引入持久连接( keep-alive ):一�?TCP 连接可传输多�?HTTP 请求
  • 默认开�?keep-alive,通常限制 6-8 个并发连�?- 存在队头阻塞问题:前面的请求阻塞会影响后续请�?- 引入 Host 字段,支持虚拟主�?- 引入 Chunk transfer 机制处理动态内容长�?

HTTP/2.0 - 多路复用

  • 一个域名只使用一�?TCP 长连�?- 引入二进制分帧层,实现多路复�?- 可对请求设置优先�?- 引入 HTTPS(HTTP + TLS) 加密

HTTP/3.0 - QUIC 协议

  • 基于 UDP 协议而非 TCP
  • 实现了类�?TCP 的流量控制和可靠传输
  • 集成 TLS 加密
  • 实现多路复用
  • 解决 TCP 队头阻塞问题

:::

参考资�?
::: details

HTTP 常见的状态码

参考答�?
::: details

  • 200 请求成功,请求在服务端被正确处理
  • 204 响应成功,没有数�?- 205 服务器处理成功,浏览器应重置文档视图
  • 206 服务器成功处理了部分get请求
  • 301 资源永久重定�?- 302 资源临时重定�?- 303 让你查看其他地址
  • 304 请求的资源没有修改,服务端不会返回任何资源,协商缓存
  • 400 请求语法错误,服务器看不�?- 401 请求没有携带信息,比�?token 认证失败
  • 403 请求被拒绝、敏感词
  • 404 找不到资�?- 500 服务器内部错误,无法完成请求
  • 501 服务器不支持当前请求所需的功�?- 503 服务器系统维护或者超载,暂时无法处理客户端的请求

:::

HTTP 常见 Header

参考答�?
::: details

请求�?

  • accept: text/html 告诉服务端我期望接收到一个html的文�?- accept-encoding: gzip, deflate, br 告诉服务端以这种方式压缩
  • accept-language: zh-CN 告诉服务端以中文的格式返�?- authorization: 告诉服务端授权信�?- cookie: 告诉服务端客户端存储�?cookie
  • origin: 告诉服务端请求的来源

响应�?

  • content-encoding: br 告诉浏览器压缩方式是br
  • content-type: text/html; charset=utf-8 告诉浏览器以这种方式,编码加�?- cache-control: 告诉浏览器缓存策�?- expires: 告诉浏览器缓存过期时�?- set-cookie: 告诉浏览器设�?cookie
  • access-control-allow-origin: * 告诉浏览器允许跨�?
    :::

URL 包含哪些部分�?

参考答�?
::: details

URL (Uniform Resource Locator) 包含以下部分�?

  1. 协议 (protocol):如 http://https://ftp:// �?

  2. 域名 (domain):如 www.example.com

    • 子域名:www
    • 主域名:example
    • 顶级域名:com
  3. 端口�?(port):如 :80:443(可选,HTTP 默认 80,HTTPS 默认 443�?

  4. 路径 (path):如 /blog/article

  5. 查询参数 (query string):如 ?id=123&name=test

  6. 锚点/片段标识�?(fragment):如 #header

示例:https://www.example.com:80/blog/article?id=123&name=test#header

:::

GET �?POST 请求的区�?

参考答�?
::: details

  • 协议层面:请求行里一定要有请求方法,官方为了统一语义,定义了 GET 表示拿数据,POST 表示上传数据,PUT 表示修改数据,所�?GET,POST 请求这里仅仅是语义上的差别,没有说哪个请求必须做�?- 应用层面:开发者约定俗成的规范,GET 请求的请求体会设空,不是没有请求�?- 浏览器层面:GET 请求会缓存,有历史记�?
    :::

Ajax Fetch Axios 三者有什么区别?

参考答�?
::: details

Ajax、Fetch �?Axios 都是用于发�?HTTP 请求的技术,但有以下区别�?
Ajax (Asynchronous JavaScript and XML)

  • 是一种技术统称,不是具体�?API
  • 最常用的实现是 XMLHttpRequest (XHR)
  • 写法比较繁琐,需要手动处理各种状�?- 回调地狱问题
  • 不支�?Promise

Fetch

  • 浏览器原�?API

  • 基于 Promise

  • 更简洁的写法

  • 不需要额外引�?- 只对网络请求报错,对 400�?00 都当做成功的请求

  • 默认不带 cookie

  • 不支持请求超时控�?- 不支持请求取�?- 不支持请求进度监�?
    Axios

  • 第三方库,需要额外引�?- 基于 Promise

  • 支持浏览器和 Node.js

  • 请求/响应拦截�?- 自动转换 JSON 数据

  • 客户端支持防�?XSRF

  • 支持请求取消

  • 支持请求超时控制

  • 支持请求进度监控

  • 支持并发请求

  • 自动转换请求和响应数�?
    使用建议�?

  • 如果是简单的请求,使�?Fetch 即可

  • 如果需要更多功能,建议使用 Axios

  • 现代项目中已经很少直接使�?XMLHttpRequest

:::

Fetch �?XMLHTTPRequest 有什么区别?

参考答�?
::: details

语法和使�?

  • Fetch 基于 Promise,代码更简洁优�?- XHR 使用回调函数,容易产生回调地�?- Fetch �?API 设计更简单现�?- XHR �?API 设计较老,使用相对复杂

功能特�?

  • Fetch 默认不发�?cookies,需要配�?credentials
  • XHR 默认发�?cookies
  • Fetch 不能监听上传进度
  • XHR 可以监听上传和下载进�?- Fetch 不能直接取消请求(需�?AbortController�?- XHR 可以通过 abort() 直接取消请求

错误处理

  • Fetch 只有网络错误才会 reject,HTTP 错误码不会导�?reject
  • XHR 可以处理所有类型的错误,包�?HTTP 错误�?
    浏览器支�?
  • Fetch 是现代浏览器标准 API
  • XHR 有更好的浏览器兼容性,包括旧版�?
    :::

什么是 Restful API �?

参考答�?
::: details

RESTful API 是一种软件架构风格,用于设计网络应用程序的接口。主要特点:

资源导向

  • 使用 URL 定位资源

  • 每个资源都有唯一�?URL

  • 资源可以有多种表现形式(�?JSON、XML�?
    HTTP 方法对应操作

  • GET:获取资�?- POST:创建资�?- PUT:更新资源(完整更新�?- PATCH:更新资源(部分更新�?- DELETE:删除资�?
    无状�?

  • 服务器不保存客户端状�?- 每个请求包含所需的所有信�?- 有利于横向扩�?
    统一接口

  • 使用标准�?HTTP 方法

  • 使用标准�?HTTP 状态码

  • 返回格式一致(通常�?JSON�?
    :::

什么是 GraphQL �?

参考答�?
::: details

GraphQL 是一种用�?API 的查询语言和运行时,由 Facebook 开发。主要特点:

查询灵活�?

  • 客户端可以精确指定需要哪些数�?- 可以在一个请求中获取多个资源
  • 避免了传�?REST API 的过度获取和获取不足问题

类型系统

  • 强类型的 Schema 定义
  • 自动生成文档
  • 开发时有更好的类型提示

单个端点

  • 只需要一�?API 端点

  • 所有查询都发送到同一个地址

  • 通过查询语句区分不同的操�?
    主要操作类型

  • Query:获取数�?- Mutation:修改数�?- Subscription:实时数据订�?
    优点

  • 减少网络请求

  • 避免版本化问�?- 强类型保�?- 更好的开发体�?
    缺点

  • 学习成本较高

  • 缓存较为复杂

  • 服务端实现复杂度增加

:::

参考答�?
::: details

Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据�?
主要特点�?

  • 由服务器生成,浏览器进行存储

  • 每次请求时会自动携带对应域名下的 cookie

  • 可设置过期时�?- 默认情况下随着浏览器关闭而删除(会话 cookie�?
    常用属性:

  • name:cookie 名称

  • value:cookie �?- domain:指�?cookie 所属域�?- path:指�?cookie 所属路�?- expires/max-age:过期时�?- secure:只�?HTTPS 下传�?- httpOnly:禁�?JS 访问

  • sameSite:跨站点请求限制

使用场景�?

  • 会话状态管理(用户登录状态、购物车等)
  • 个性化设置(用户偏好、主题等�?- 浏览器行为跟踪(分析用户行为等)

限制�?

  • 大小限制:通常�?4KB
  • 数量限制:每个域名下�?cookie 数量有限
  • 安全性:明文传输(除非使�?HTTPS�?- 作用域:只能在所属域名下使用

:::

参考答�?
::: details

主要原因是保护用户隐私和安全�?
隐私问题

  • 第三�?Cookie 可以跨站点追踪用户行�?- 广告商可以构建用户画像和浏览历史
  • 用户数据可能被未经授权收集和使用

安全风险

  • 增加 CSRF(跨站请求伪造)攻击风险
  • 可能被用于会话劫�?- 恶意网站可能滥用第三�?Cookie

技术影�?

  • Safari �?Firefox 已默认禁用第三方 Cookie
  • Chrome 计划�?2024 年完全禁用第三方 Cookie
  • 替代方案�? - First-Party Cookie
    • localStorage
    • Privacy Sandbox
    • FLoC (Federated Learning of Cohorts)

:::

如何理解 Session �?

参考答�?
::: details

Session 是服务器端的会话管理机制�?
基本概念

  • 服务器为每个用户创建的临时会话存储空�?- 用于保存用户的会话状�?- 通过 SessionID 来识别不同用�?- SessionID 通常保存�?Cookie �?
    工作流程
  1. 用户首次访问服务器时,服务器创建 Session 并生�?SessionID
  2. 服务器将 SessionID 通过 Cookie 发送给客户�?3. 客户端后续请求会自动携带包含 SessionID �?Cookie
  3. 服务器通过 SessionID 找到对应 Session 并识别用�?
    特点
  • 安全性较高:敏感数据存储在服务器
  • 服务器负载较大:需要存储所有用户的 Session
  • 依赖 Cookie:通常需�?Cookie 来存�?SessionID
  • 集群问题:需要考虑 Session 共享

使用场景

  • 用户登录状态管�?- 购物�?- 权限验证
  • 表单验证

�?Cookie 的区�?

  • 存储位置:Session 在服务器,Cookie 在客户端
  • 安全性:Session 较安全,Cookie 相对不安�?- 存储容量:Session 容量较大,Cookie 通常限制 4KB
  • 性能:Session 消耗服务器资源,Cookie 消耗带宽资�?
    :::

什么是 JWT 描述它的工作过程

参考答�?
::: details

JWT (JSON Web Token) 是一种开放标准,用于在各方之间安全地传输信息�?
组成部分(用 . 分隔的三部分):

  • Header(头部):指定加密算法和令牌类型
  • Payload(负载):包含声明(claims)的实际数据
  • Signature(签名):对前两部分的签名,用于验证消息未被篡改

工作流程�?

  1. 用户登录成功后,服务器创�?JWT

    • 设置 Header �?Payload
    • 使用密钥生成签名
    • 将三部分组合�?token
  2. 服务器将 token 返回给客户端

    • 客户端存储在 localStorage �?cookie �?
  3. 后续请求携带 token

    • 通常放在 Authorization header
    • 格式:Bearer <token>
  4. 服务器验�?token

    • 检查签名是否有�? - 验证是否过期
    • 验证其他声明(claims�?
      特点�?
  • 无状态:服务器不需要存储会话信�?- 可扩展:负载部分可以包含自定义数�?- 跨域友好:可以在不同域名下使�?- 性能好:验证在服务端完成,不需要查询数据库

安全考虑�?

  • 不要�?payload 中存储敏感信�?- 设置合理的过期时�?- 使用 HTTPS 传输
  • 妥善保管签名密钥

:::

参考资�?
::: details

:::

JWT 如何自动更新 token �?

参考答�?
::: details

JWT token 自动更新主要有以下几种方案:

�?token 机制

  • access token:短期令牌,用于接口认证
  • refresh token:长期令牌,用于刷新 access token
  • 优点:安全性高,即�?access token 泄露影响有限
  • 缺点:实现相对复杂,需要额外存�?refresh token

工作流程�?

  1. 用户登录后获�?access token �?refresh token
  2. 使用 access token 访问接口
  3. access token 过期时,使用 refresh token 获取新的 access token
  4. refresh token 过期时,需要重新登�?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    // 前端示例代码
    async function request(url, options) {
    try {
    const res = await fetch(url, {
    ...options,
    headers: {
    Authorization: `Bearer ${getAccessToken()}`,
    },
    })

    if (res.status === 401) {
    // access token 过期,尝试刷�? const newToken = await refreshToken()
    if (newToken) {
    // 使用�?token 重试请求
    return request(url, options)
    } else {
    // refresh token 也过期,跳转登录
    redirectToLogin()
    }
    }

    return res
    } catch (error) {
    console.error(error)
    }
    }

滑动过期机制

  • 每次请求都刷�?token 过期时间

  • 类似于会话超时机�?- 优点:实现简单,用户体验�?- 缺点:安全性相对较�?
    无感刷新机制

  • �?token 即将过期时自动刷�?- 可以通过定时器或请求拦截器实�?- 优点:用户无感知,体验好

  • 缺点:需要处理并发请求的问题

最佳实践:

  • 根据业务安全需求选择合适的方案
  • access token 过期时间不宜过长(如 2 小时�?- refresh token 过期时间可以较长(如 7 天)
  • 重要操作仍需要二次验�?- 考虑 token 注销机制

:::

什么是 SSO 单点登录,描述它的工作过�?

参考答�?
::: details

SSO (Single Sign On) 单点登录是一种身份验证机制,允许用户使用一组凭证访问多个相关但独立的系统�?
基本概念

  • 一次登录,全局通用

  • 多个子系统共享用户会�?- 统一的认证中�?- 提高用户体验和安全�?
    工作流程�?
    用户首次访问系统

  • 用户访问系统 A

  • 系统 A 检查无登录状�?- 重定向到 SSO 认证中心

  • 带上系统 A 的地址作为参数

SSO 认证中心处理

  • 检查用户是否已登录 SSO
  • 未登录则显示登录页面
  • 用户输入账号密码
  • 认证中心验证身份

回到系统 A

  • SSO 生成票据(ticket�?- 重定向回系统 A
  • 带上票据参数
  • 系统 A 验证票据
  • 创建本地会话

访问系统 B

  • 用户访问系统 B
  • 系统 B 检查无登录状�?- 重定向到 SSO 认证中心
  • SSO 发现用户已登�?- 直接生成票据返回
  • 系统 B 验证票据
  • 创建本地会话

实现方式�?

  • 基于 Cookie
  • 基于 Token
  • 基于 SAML
  • 基于 OAuth
  • 基于 CAS

优点�?

  • 提升用户体验
  • 减少密码管理
  • 统一认证流程
  • 提高安全�?
    缺点�?
  • 认证中心单点故障
  • 配置相对复杂
  • 需要额外的安全考虑

:::

参考资�?
::: details

:::

什么是跨域?如何实现跨域通讯�?

参考答�?
::: details

跨域是指浏览器的同源策略限制,当前域名的 JavaScript 代码试图访问其他域名下的资源时会受到限制�?
同源的定义:

  • 协议相同(http/https�?- 域名相同
  • 端口相同

跨域解决方案�?
CORS(跨域资源共享)

  • 服务器设�?Access-Control-Allow-Origin 等响应头

  • 可以配置允许的请求方法、请求头、是否允许携带认证信息等

  • 最常用的跨域解决方�?
    JSONP

  • 利用 <script> 标签不受同源策略限制的特�?- 只支�?GET 请求

  • 需要服务器配合返回 JavaScript 代码

代理服务�?

  • 开发环境:webpack-dev-server、vite 等的 proxy 配置
  • 生产环境:Nginx 反向代理

postMessage

  • HTML5 标准中的 API
  • 用于不同窗口间的跨域通信
  • 可以在父子页面(iframe)或者多窗口间通信

WebSocket

  • 建立�?TCP 之上的协�?- 天然支持跨域

  • 适合需要实时通信的场�?
    document.domain(已废弃�?

  • 仅适用于主域名相同的情�?- 将子域和主域�?document.domain 设为相同的主�?
    最佳实践:

  • 优先使用 CORS,配置得当的情况下最安全

  • 需要兼容旧浏览器时可以考虑 JSONP

  • 开发环境优先使用代理服务器

  • 特殊场景(如页面通信)可以考虑 postMessage

  • 需要实时通信时使�?WebSocket

:::

参考资�?
::: details

:::

HTTP 请求跨域时为何要发�?options 请求

参考答�?
::: details

OPTIONS 请求�?CORS 预检请求(Preflight Request),用于检查实际请求是否可以安全地发送�?
触发条件�?

  • 使用非简单请求方法:�?GET、POST、HEAD 之外的方�?- 使用非简单请求头:除 Accept、Accept-Language、Content-Language、Content-Type 之外的请求头
  • Content-Type 不是以下之一�? - application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

工作流程�?

  1. 浏览器发�?OPTIONS 预检请求,包含:

    • Origin:请求来�? - Access-Control-Request-Method:实际请求使用的方法
    • Access-Control-Request-Headers:实际请求使用的请求�?
  2. 服务器响应预检请求,返回:

    • Access-Control-Allow-Origin:允许的�? - Access-Control-Allow-Methods:允许的方法
    • Access-Control-Allow-Headers:允许的请求�? - Access-Control-Max-Age:预检请求的缓存时�?
  3. 如果预检通过,浏览器才会发送实际请�?
    优化建议�?

  • 尽可能使用简单请求,避免触发预检
  • 合理设置 Access-Control-Max-Age 缓存预检结果
  • 服务端正确配�?CORS 响应�?
    :::

参考资�?
::: details

:::

参考答�?
::: details

OPTIONS 请求通常不会携带 Cookie。它是一个预检请求,用于检查实际请求是否可以安全地发送。浏览器在发�?OPTIONS 请求时,不会自动附带 Cookie �?Authorization 等认证信息,除非明确设置�?credentials 选项�?
如果需要在 OPTIONS 请求中携�?Cookie,可以在请求中设�?credentials: 'include',但通常不推荐这样做,因�?OPTIONS 请求的目的就是检查跨域请求的安全性,而不是进行身份验证�?
:::

简述浏览器的缓存策�?

参考答�?
::: details

浏览器缓存策略主要分为两种:强缓存和协商缓存�?
强缓�?

  • 不需要向服务器发送请求,直接使用本地缓存

  • 通过 HTTP 响应头控制:

    • Cache-Control�? - max-age:缓存有效时间(秒)
      • no-cache:需要和服务器协商验�? - no-store:不使用任何缓存
      • private:仅浏览器可缓存
      • public:中间代�?CDN 等也可缓�? - Expires:过期时间点(已�?Cache-Control 取代�?
        协商缓存
  • 需要向服务器发送请求验证资源是否有�?- 如果有效返回 304,使用本地缓�?- 通过以下响应头实现:

    • Last-Modified/If-Modified-Since:基于文件修改时�? - ETag/If-None-Match:基于文件内容哈希�?
      缓存位置(优先级从高到低):
  1. Service Worker
  2. Memory Cache(内存缓存)
  3. Disk Cache(硬盘缓存)
  4. Push Cache(HTTP/2�?
    最佳实践:
  • HTML:使用协商缓�?- CSS、JS、图片:使用强缓存,文件名带 hash
  • API 请求:根据业务需求设置合适的缓存策略

:::

参考资�?
::: details

:::

什么是图片防盗链,如何实现�?

参考答�?
::: details

图片防盗链是指服务器通过 HTTP 协议中的 Referer 字段来判断请求是否来自合法站点,从而防止其他网站直接引用本站图片资源�?
实现方式�?
服务器端实现

  • 检�?HTTP Referer 字段
  • 判断请求来源是否在白名单�?- 对非法请求返�?403 或替代图�?
    Nginx 配置示例�?
    1
    2
    3
    4
    5
    6
    7
    location ~ .*\.(gif|jpg|jpeg|png|bmp)$ {
    valid_referers none blocked server_names *.example.com;
    if ($invalid_referer) {
    return 403;
    # 或者返回替代图�? # rewrite ^/ /path/to/default.jpg break;
    }
    }

其他防盗链方案:

  • 给图片添加水�?- 使用 Token 验证
  • 使用 CDN 提供的防盗链功能
  • 对图片进行加密处�?
    注意事项�?
  • Referer 可以被伪造,不能作为唯一判断依据
  • 移动�?APP 可能不发�?Referer
  • 部分浏览器可能禁�?Referer
  • 需要考虑用户体验�?SEO 影响

:::

简�?HTTPS 加密过程

参考答�?
::: details

HTTPS 使用 TLS/SSL 协议进行加密,主要包含以下步骤:

客户端发起请�?

  • 发送支持的加密算法列表
  • 发送随机数 Client Random

服务器回�?

  • 选择加密算法
  • 发送数字证书(包含公钥�?- 发送随机数 Server Random

客户端验证证�?

  • 验证证书是否由可�?CA 签发

  • 验证证书域名是否匹配

  • 验证证书是否在有效期�?
    生成会话密钥

  • 客户端生成随机数 Pre-master secret

  • 使用服务器公钥加�?Pre-master secret

  • 客户端和服务器都通过三个随机数生成会话密�? (Client Random + Server Random + Pre-master secret)

开始加密通信

  • 双方使用会话密钥进行对称加密通信
  • 保证通信内容的机密性和完整�?
    特点�?
  • 采用混合加密:非对称加密传输密钥,对称加密传输数�?- 数字证书保证服务器身份可�?- 具有防篡改和不可否认�?
    :::

移动�?H5 如何抓包�?

参考答�?
::: details

移动�?H5 抓包主要有以下几种方法:

Charles/Fiddler

  • 电脑端安装抓包工�?- 手机和电脑连接同一网络
  • 手机设置代理为电�?IP 和端�?- 安装并信任证书(HTTPS 抓包需要)

优点�?

  • 功能强大,可以查看详细请求信�?- 支持请求修改和重�?- 支持断点调试

vConsole

  • 移动端调试面�?- 直接在页面中引入 js 文件
  • 可以查看网络请求、console 日志�?- 适合开发环境使�?
    1
    2
    3
    4
    <script src="https://unpkg.com/vconsole/dist/vconsole.min.js"></script>
    <script>
    var vConsole = new VConsole();
    </script>

Chrome Remote Debug

  • 安卓设备通过 USB 连接电脑
  • 开启开发者模式和 USB 调试
  • Chrome 访问 chrome://inspect
  • 可以使用完整�?Chrome DevTools

Safari Web Inspector

  • iOS 设备通过 USB 连接 Mac
  • 开�?Web 检查器
  • Safari 开发菜单中选择设备
  • 可以使用完整�?Safari 调试工具

注意事项�?

  • HTTPS 抓包需要安装证�?- 部分 App 可能有反抓包机制
  • 生产环境建议移除调试工具
  • 注意数据安全和隐私保�?
    :::

script 标签�?defer �?async 有什么区�?

参考答�?
::: details

script 标签�?defer �?async 属性都是用于控制脚本的加载和执行时机:

普�?script

  • 阻塞 HTML 解析

  • 立即下载并执行脚�?- 按照在文档中的顺序执�?
    defer

  • 异步下载脚本,不阻塞 HTML 解析

  • 等到 HTML 解析完成后,DOMContentLoaded 事件触发前执�?- 多个 defer 脚本按照在文档中的顺序执�?- 适用于需要操�?DOM 的脚�?- 只对外部脚本文件有效

async

  • 异步下载脚本,不阻塞 HTML 解析
  • 下载完成后立即执行,可能�?HTML 解析完成前执�?- 多个 async 脚本的执行顺序不确定,取决于下载完成时间
  • 适用于独立的脚本,如统计和广告代�?- 只对外部脚本文件有效

使用建议�?

  • 需要操�?DOM 或依赖其他脚本的代码使用 defer
  • 独立的、不依赖 DOM 和其他脚本的代码使用 async
  • 如果脚本之间有依赖关系,不要使用 async

示例�?

1
2
3
4
5
6
7
8
<!-- 普通脚�?-->
<script src="script.js"></script>

<!-- defer 脚本 -->
<script defer src="script.js"></script>

<!-- async 脚本 -->
<script async src="script.js"></script>

:::

prefetch �?dns-prefetch 分别是什�?

参考答�?
::: details

prefetch �?dns-prefetch 是两种不同的资源预加载技术:

prefetch

  • 用于预加载将来可能需要的资源
  • 浏览器空闲时才会下载
  • 优先级较低,不影响当前页面加�?- 适用于下一页可能用到的资源
1
2
3
<!-- 预加载资�?-->
<link rel="prefetch" href="/next-page.js" />
<link rel="prefetch" href="/images/large.jpg" />

dns-prefetch

  • 预先解析域名�?DNS 记录
  • 减少 DNS 解析时间
  • 适用于即将请求其他域名的资源
  • 对跨域资源加载特别有�?
    1
    2
    3
    <!-- DNS 预解�?-->
    <link rel="dns-prefetch" href="//example.com" />
    <link rel="dns-prefetch" href="//api.example.com" />

使用建议�?

  • 对确定即将访问的资源使用 prefetch

  • 对跨域资源较多的站点使用 dns-prefetch

  • 不要过度预加载,可能浪费带宽

  • 移动端要谨慎使用,考虑流量消�?
    相关技术:

  • preload:当前页面必需资源的预加载

  • preconnect:预先建立连接(DNS + TCP + TLS�?- prerender:预先渲染整个页�?
    :::

WebSocket �?HTTP 协议有什么区�?

参考答�?
::: details

WebSocket �?HTTP 的主要区别:

连接特�?

  • HTTP 是短连接:每次请求都需要建立新�?TCP 连接(除非使�?keep-alive�?- WebSocket 是持久化的长连接:只需要一次握手,后续可以持续通信

通信方式

  • HTTP 是单向通信:客户端请求,服务器响应

  • WebSocket 是双向通信:客户端和服务器都可以主动发送数�?
    数据格式

  • HTTP 每次请求都要带完整的 HTTP �?- WebSocket 第一次握手完成后,后续数据传输只需要很小的头部

应用场景

  • HTTP 适合一次性的数据交互
  • WebSocket 适合实时性要求高的场景,如:
    • 实时聊天
    • 游戏实时数据
    • 实时协作文档

性能

  • WebSocket 的性能和效率通常优于 HTTP 轮询
  • WebSocket 可以更好地节省服务器资源和带�?
    支持�?
  • HTTP 被所有浏览器支持
  • WebSocket 需要浏览器支持(现代浏览器普遍已支持)

:::

如何上传文件?使�?fetch 或�?axios

参考答�?
::: details

文件上传主要有以下几种方式:

使用 FormData

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// HTML
<input type="file" id="file">

// fetch
const file = document.querySelector('#file').files[0]
const formData = new FormData()
formData.append('file', file)

fetch('/upload', {
method: 'POST',
body: formData
})

// axios
const formData = new FormData()
formData.append('file', file)

axios.post('/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})

使用 Base64

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 将文件转�?Base64
function fileToBase64(file) {
return new Promise((resolve) => {
const reader = new FileReader()
reader.onload = () => resolve(reader.result)
reader.readAsDataURL(file)
})
}

// fetch
const base64 = await fileToBase64(file)
fetch('/upload', {
method: 'POST',
body: JSON.stringify({ file: base64 }),
headers: {
'Content-Type': 'application/json',
},
})

// axios
const base64 = await fileToBase64(file)
axios.post('/upload', {
file: base64,
})

多文件上�?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// HTML
<input type="file" multiple id="files">

// fetch
const files = document.querySelector('#files').files
const formData = new FormData()
Array.from(files).forEach(file => {
formData.append('files', file)
})

fetch('/upload', {
method: 'POST',
body: formData
})

// axios
const formData = new FormData()
Array.from(files).forEach(file => {
formData.append('files', file)
})

axios.post('/upload', formData)

注意事项�?

  • 设置正确�?Content-Type
  • 考虑文件大小限制
  • 添加上传进度显示
  • 处理上传错误
  • 考虑文件类型限制
  • 添加取消上传功能

:::

如何上传大文件?

参考答�?
::: details

大文件上传主要有以下几种方案�?
切片上传

  • 将大文件分割成小�?- 并发上传多个切片
  • 服务端合并所有切�?- 支持断点续传和进度显�?
    实现步骤�?前端切片
1
2
3
4
5
6
7
8
9
function createFileChunk(file, size = 1 * 1024 * 1024) {
const chunks = []
let cur = 0
while (cur < file.size) {
chunks.push(file.slice(cur, cur + size))
cur += size
}
return chunks
}

上传切片

1
2
3
4
5
6
7
8
9
async function uploadChunks(chunks) {
const requests = chunks.map((chunk, index) => {
const formData = new FormData()
formData.append('chunk', chunk)
formData.append('index', index)
return axios.post('/upload', formData)
})
await Promise.all(requests)
}

发送合并请�?

1
2
3
4
await axios.post('/merge', {
filename: file.name,
size: chunks.length,
})

断点续传

  • 记录已上传的切片

  • 重新上传时跳过已上传的部�?- 可以通过 localStorage 存储进度

  • 使用 hash 标识文件和切�?
    秒传

  • 上传前先发送文�?hash

  • 服务端存在相同文件则直接返回

  • 可以使用 spark-md5 计算文件 hash

性能优化

  • 并发控制:限制同时上传的切片�?- 切片大小:根据网络状况动态调�?- 进度显示:计算整体上传进�?- 错误重试:单个切片上传失败后重试

:::

参考资�?
::: details

:::

如何实现图片懒加载?

参考答�?
::: details

IntersectionObserver API

1
2
3
4
5
6
7
8
9
10
11
12
13
const io = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.src = entry.target.dataset.original
entry.target.removeAttribute('data-original')
io.unobserve(entry.target)
}
})
})
const imgs = document.querySelectorAll('img[data-original]')
imgs.forEach((item) => {
io.observe(item)
})

原生 loading 属�?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let viewHeight = window.innerHeight
function lazyLoad() {
let imgs = document.querySelectorAll('img[data-original]')
imgs.forEach((el) => {
let rect = el.getBoundingClientRect()
if (rect.top < viewHeight) {
let image = new Image()
image.src = el.dataset.original
image.onload = function () {
el.src = image.src
}
el.removeAttribute('data-original')
}
})
}
lazyLoad() // 页面初始加载时调用一�?document.addEventListener('scroll', lazyLoad)

:::

参考资�?
::: details

:::

在网络层面可做哪些性能优化�?

参考答�?
::: details

网络性能优化可以从以下几个方面考虑�?
减少请求数量

  • 合并文件(CSS/JS 打包�?- 雪碧图(CSS Sprites�?- 图片懒加�?- 按需加载/异步加载
  • 合理使用缓存

减小资源体积

  • 代码压缩(minify�?- Gzip/Brotli 压缩

  • 图片优化(压缩、webp格式�?- Tree Shaking

  • 代码分割(Code Splitting�?
    CDN 优化

  • 使用 CDN 分发静态资�?- 合理设置 CDN 缓存

  • 选择合适的 CDN 节点

  • 配置 CDN 预热和刷新策�?
    HTTP 优化

  • 使用 HTTP/2 多路复用

  • 开�?Keep-Alive

  • 合理设置缓存策略

  • DNS 预解析(dns-prefetch�?- 预连接(preconnect�?- 预加载(prefetch/preload�?
    资源加载优化

  • 关键资源优先加载

  • 非关键资源延迟加�?- 内联关键 CSS/JS

  • 异步加载非关�?JS(async/defer�?- 优化资源加载顺序

接口优化

  • 接口合并
  • GraphQL 按需查询
  • 数据缓存
  • 避免重复请求
  • 设置合理的超时时�?
    监控和分�?
  • 性能监控
  • 错误监控
  • 用户体验监控
  • 性能数据分析
  • 持续优化

:::

参考资�?
::: details

:::