Skip to content

浏览器与网络 ​

搜索引擎与 SEO、跨域、存储、渲染、缓存、传输协议(TCP / UDP / WebSocket)、HTTP 与常见 Web 安全。垃圾回收、事件冒泡 / 捕获 / 委托见 JavaScript。

性能边界:本章讲浏览器为什么卡(重排 / 重绘 / 合成)。项目「加载 / 打包 / 懒加载」清单见 工程化;Vue 组件 API 手段见 Vue3。

搜索引擎是怎么工作的?前端 SEO 怎么做? ​

搜索引擎(Google、百度等)不是地址栏那个搜索框,而是一套抓取 → 索引 → 排名的系统。SEO(搜索引擎优化)就是让页面更容易被抓到、看懂、排到前面。前端 常问:爬虫怎么拿页面、SPA(单页应用)为啥不利于 SEO、前端能改什么。

1. 搜索引擎三步:抓取、索引、排名 ​

  • 抓取(Crawl):爬虫像简化版浏览器去请求 URL,拿到 HTML,顺着 <a> 继续发现新页。也会读 robots.txt(爬虫协议),决定哪些路径不抓。
  • 索引(Index):解析标题、正文、结构、链接,存进索引库。页面「说了什么」主要看 HTML 文本,不只看用户肉眼看到的画面。
  • 排名(Rank):用户搜关键词时排出先后。相关度看内容和搜索词匹不匹配;站点权威看这个站靠不靠谱、有没有分量(别的正规站会不会链过来,前端几乎改不了);页面体验看速度、移动端、HTTPS。

⚠️ 关键点:用户用 Chrome 打开能看见内容,不代表爬虫一定能看见。爬虫优先吃 HTML;CSR(客户端渲染,页面靠浏览器跑 JS 再画出内容)的 SPA,首包经常是空的 #app,正文要等 JS 跑完才有。

2. 和浏览器 / SPA 的关系 ​

渲染方式爬虫拿到的 HTMLSEO 友好度
传统 MPA(多页应用)/ SSR(服务端渲染)首包就是完整正文好
SSG(静态站点生成)/ 预渲染构建时已生成完整 HTML好
CSR(客户端渲染,典型 Vue / React 单页应用)往往只有空壳 + JS差,除非再做 SSR / 预渲染

现代 Google 能执行一部分 JS(网页渲染服务,基于 Chrome),但不保证及时、完整;百度等对 JS 更弱。 默认答:不能把 SEO 赌在「爬虫会跑 JS」上,要收录的公开页该让 HTML 里先有正文。

怎么解(同一类问题,三种手段):

  • SSR(服务端渲染):每次请求服务器当场渲成带正文的 HTML。适合内容常变、要个性化的页。
  • SSG(静态站点生成):构建时生成完整 HTML。适合官网、文档、博客。
  • 预渲染:仍是 SPA,打包时用无头浏览器把公开路由打开并存成 HTML。已有 Vite + Vue 官网改动最小:路由用 History(不要 hash),只预渲染要被搜到的页。

官网一般用 SSG 或预渲染即可,不必上 SSR。后台、登录页继续 CSR 没问题。

3. 前端能做的 SEO(按 优先级) ​

让爬虫「看见」内容

  • 公开页用 SSR(服务端渲染)/ SSG(静态站点生成)/ 预渲染,不要只靠 CSR(客户端渲染)
  • 语义化 HTML:一页一个 h1,用 header / nav / main / article,别全是 div(标签本身怎么写,见 HTML 语义化)
  • 重要文案写在 HTML 里,不要只画在 canvas(画布)或纯图片里

让爬虫「看懂」这页是什么

  • <title>、<meta name="description">:出现在搜索结果的标题和摘要
  • 图片写 alt(替代文本),链接用有意义的锚文本
  • canonical(规范网址)指定这一页的标准 URL,避免重复页抢权重
  • 结构化数据 JSON-LD(一种给搜索引擎读的标注格式,可选,用来做富摘要)

让爬虫「找得到、愿意排」

  • robots.txt(爬虫协议)声明哪些不抓;sitemap.xml(站点地图)把该收录的 URL 列出来
  • 站内链接能点到关键页(爬虫靠链接发现页面)
  • HTTPS、移动端适配
  • 性能:Core Web Vitals(网页核心体验指标:LCP 最大内容绘制、INP 交互响应、CLS 布局偏移)已是排名因素之一,和「页面体验」挂钩

🎤 口述背诵版 ​

搜索引擎三步:爬虫抓 HTML、解析进索引、按相关度和体验排名。SEO(搜索引擎优化)就是让这三步都对你有利。

前端最容易踩的坑是 SPA(单页应用):用户能看见,爬虫首包可能是空壳。解法是让 HTML 里先有正文:SSR(服务端渲染)、SSG(静态站点生成)、预渲染都算,不是只有 SSR。官网优先 SSG 或预渲染。

除此之外:语义化标签、title / description、图片 alt(替代文本)、sitemap(站点地图)/ robots(爬虫协议)、HTTPS 和速度。能讲清「爬虫看的是 HTML,不是你渲染完的画面」,这题就过了。

什么是 XSS 和 CSRF?如何预防? ​

XSS(跨站脚本) ​

攻击者把恶意脚本注入到页面,浏览器当作正常页面逻辑执行。常见危害:窃取 Cookie / 本地存储、篡改页面、冒充用户发请求。

常见分类:

类型特点
存储型恶意内容写入服务端(评论、资料等),他人打开页面即中招
反射型恶意内容挂在 URL 参数里,服务端原样反射进页面后执行
DOM 型不经过服务端,前端用 JS 把不可信数据写进 DOM(如 innerHTML)后执行

预防:

  • 输入校验、输出编码 / 转义(把用户内容当数据,不当代码)
  • 少用 innerHTML / v-html 等会按 HTML 解析的 API;Cookie 可加 HttpOnly(禁止 JS 读 Cookie),降低被脚本读取的风险
  • 配 CSP(内容安全策略,Content-Security-Policy),限制脚本来源、减少内联脚本执行面

CSRF(跨站请求伪造) ​

在用户已登录的前提下,诱导其访问恶意站点或链接,借浏览器自动携带 Cookie 的特性,向目标站发起用户非本意的请求(改资料、转账等)。攻击方通常拿不到 Cookie 内容,只是「借身份办事」。

预防:

  • CSRF Token(跨站请求令牌):敏感请求携带服务端下发、攻击站无法读取的 token,服务端校验
  • 校验 Referer / Origin(来源),确认请求来自本站
  • Cookie 设置 SameSite(同站策略:Lax / Strict),限制跨站请求自动带 Cookie
  • 关键操作可再加二次验证(密码、短信等)

XSS vs CSRF ​

XSSCSRF
本质在页面里跑恶意脚本借登录态发请求
典型结果偷数据、改页面、进一步攻击在不知情下完成敏感操作
防护重心输入输出转义、CSP、避免危险 DOM APIToken、SameSite、来源校验

🎤 口述精简版 ​

XSS 是往页面注入并执行恶意脚本,防转义 / 少用危险渲染、配 CSP、Cookie 可加 HttpOnly。CSRF 是借你已登录的 Cookie 冒充你发请求,防 CSRF Token、SameSite、校验 Origin / Referer。一个防「脚本被执行」,一个防「请求不是你本意」。

什么是跨域?跨域产生的原因? ​

1. 什么是跨域 ​

当协议、域名、端口三者任意一个不一样,就是跨域。

  • ✅ 同源:http://a.com:8080 → http://a.com:8080 协议、域名、端口全部相同
  • ❌ 跨域:只要协议 / 域名 / 端口,有任意一项不同,就属于跨域

注意:跨域是浏览器的安全限制;请求是正常发出去了,后端收到请求,浏览器拿到响应之后,被浏览器拦截,不给 JS 读取响应结果。不是请求发不出去。

2. 跨域产生的根本原因:浏览器的同源策略(Same-Origin Policy) ​

同源策略是浏览器的安全机制,目的:防止恶意网站窃取另外一个网站的敏感数据,保护用户安全。

它限制两件主要事情:

  • JS 不能读取不同源的 DOM、Cookie、localStorage 等页面数据
  • JS 无法正常读取跨域的 AJAX/Fetch 接口响应(接口请求可以发出,响应被浏览器拦截)

⚠️ 关键点:

  • 同源策略只存在于浏览器环境,后端服务器之间互相请求不存在跨域;Postman、后端代码调用接口没有跨域问题
  • <img>、<script>、<link> 标签加载资源不受同源策略限制(所以才有 JSONP 的实现思路)

🎤 口述简短背诵版 ​

跨域是浏览器同源策略带来的现象。浏览器判断同源看协议、域名、端口,三者有一个不一样就是跨域。

同源策略是浏览器的安全保护机制,为了防止恶意站点窃取其他网站的数据。

跨域的时候,请求实际是发送到后端,后端也处理返回了,只是浏览器拦截了 JS 对响应的读取。

注意:后端与后端之间调用接口不存在跨域。

常见跨域解决方案:CORS、JSONP、代理、Nginx 的原理和优缺点? ​

重点:分清哪一端做改造、原理、优点、缺点。

1. CORS(跨域资源共享,后端主流方案) ​

改造位置:服务端(后端)

原理:

  • 浏览器发现请求跨域,会自动带上 Origin 请求头;后端在响应头增加 Access-Control-Allow-Origin 等系列响应头,告诉浏览器允许该源访问
  • 简单请求:直接一次请求
  • 非简单请求(PUT/DELETE、自定义 header 等):浏览器先发 OPTIONS 预检请求,预检通过才发真实请求

优点:

  • 支持所有请求方式 GET/POST/PUT/DELETE;支持 cookie 携带
  • W3C 标准,现代浏览器全部支持,业务首选

缺点:

  • 需要后端修改代码配置响应头,前端无改动
  • 老 IE 浏览器不支持(IE8/9 部分兼容)
  • 非简单请求会多出一次 OPTIONS 预检请求,产生额外网络开销

2. JSONP ​

改造位置:前端 + 后端配合

原理:

  • 利用 <script> 标签不受同源策略限制的特性
  • 前端动态创建 script 标签,请求后端接口,后端返回一段回调函数调用的 JS 脚本,把数据作为回调参数传回前端

优点:

  • 兼容非常老浏览器;没有预检请求

缺点:

  • 只支持 GET 请求,不支持 POST/PUT 等
  • 存在 XSS 安全风险,后端需要校验回调参数
  • 不能携带 cookie
  • 属于 hack 方案,现在新项目基本不用

3. 开发环境代理(Vue/Vite/Webpack devServer 代理) ​

改造位置:前端工程配置,仅本地开发阶段生效

原理:浏览器请求本地前端服务(同源),前端开发服务器充当中间转发服务器,把请求转发给真实后端接口;浏览器只和本地服务通信,不存在跨域。

⚠️ 重要:仅开发环境生效,打包上线后该代理配置完全失效!上线不能靠这个解决跨域。

优点:前端自己配置,不需要改后端代码,本地调试非常方便。

缺点:只用于本地开发,生产环境无效。上线必须 CORS/Nginx。

4. Nginx 反向代理 ​

改造位置:运维 / Nginx 服务器

原理:部署 Nginx 服务器。前端页面和接口统一走同一个 Nginx 域名。浏览器访问同源 Nginx 地址,Nginx 收到请求,内部转发到真实后端服务。浏览器只跟 Nginx 通信,无跨域。

两种用法:

  • 前端静态资源 + 接口全部由 Nginx 代理
  • 单独把 /api 路径转发到后端服务

优点:

  • 不需要前后端改业务代码;对前端完全透明
  • 支持所有请求方式,支持 cookie,生产环境稳定

缺点:需要运维配置 Nginx 服务器;需要服务器权限。

方案修改方适用环境支持 POST主要缺点
CORS后端生产 / 开发✅需要后端修改,非简单请求有 OPTIONS 预检
JSONP前后端配合老浏览器兼容❌ 仅 GETXSS 风险,新项目废弃
devServer 代理前端工程配置仅本地开发✅打包后失效,线上无效
Nginx 反向代理运维 Nginx生产环境✅需要服务器配置权限

🎤 口述背诵版 ​

四种跨域方案:

CORS:后端配置响应头,W3C 标准,支持各种请求,是生产最常用;缺点需要后端改造,非简单请求会有 OPTIONS 预检。

JSONP:利用 script 标签不受同源限制;只能 GET,有 XSS 风险,新项目几乎不用。

前端工程代理:webpack/vite 的 devServer 代理,只用于本地开发,打包上线无效,不能解决线上跨域。

Nginx 反向代理:运维配置,统一域名转发请求,浏览器无跨域,不需要修改前后端业务代码,生产环境常用,但是需要服务器权限。

补充一句 高频踩坑:开发环境代理不能用于线上,线上跨域要么后端 CORS,要么 Nginx 代理。

cookie、localStorage、sessionStorage 的区别? ​

限定对比维度:存储大小、生命周期、是否随请求发送、作用域、设置方式。

注意:符合 domain、path 规则的 Cookie,浏览器才会自动在请求头带上 Cookie 字段发给服务端;不匹配则不会携带,不是无条件全部携带。domain / path 决定哪些请求会带上这个 cookie。

特性CookielocalStoragesessionStorage
存储大小约 4KB约 5MB约 5MB
生命周期可设置过期时间(expires/max-age);不设置则浏览器全关后失效永久存储,需手动清除才消失当前标签页关闭即销毁,刷新页面保留
是否随请求发送匹配 domain、path 时自动携带到请求头不会自动发送,仅前端 JS 操作不会自动发送,仅前端 JS 操作
作用域domain + path 控制,配置后可在对应域名下访问同源(协议 + 域名 + 端口),多标签页共享同源,仅当前标签会话,同域名多标签互相隔离
设置方式主要由后端通过响应头 Set-Cookie 设置;前端 JS 也可通过 document.cookie 读写(受 HttpOnly 限制)前端 JS 操作:setItem / getItem / removeItem / clear前端 JS 操作:setItem / getItem / removeItem / clear

🎤 口述精简版 ​

从存储大小、生命周期、是否随请求发送、作用域、设置方式五个维度来讲:

存储大小:cookie 只有 4KB,localStorage 和 sessionStorage 大概 5MB。

生命周期:cookie 可以设置过期时间;localStorage 永久保存,需要手动清除;sessionStorage 关闭当前标签页就销毁。

是否随请求发送:cookie 在满足 domain、path 匹配时,会自动携带到 http 请求头;localStorage、sessionStorage 不会随请求发送,只能前端 JS 操作。

作用域:cookie 受 domain 和 path 控制,可以在配置的域名下访问;localStorage 同源多标签页共享;sessionStorage 只在当前标签会话可用,同域名不同标签互相隔离。

设置方式:cookie 一般由后端通过 Set-Cookie 响应头设置,前端也能用 document.cookie 读写(有 HttpOnly 时 JS 读不到);localStorage 和 sessionStorage 都是前端用 setItem / getItem / removeItem / clear 操作。

浏览器页面渲染完整流程? ​

常问「从输入 URL 到页面展示发生了什么」,按网络 → 解析 → 渲染来讲:

  1. DNS 解析(域名 → IP,有缓存)
  2. TCP 三次握手(HTTPS 还多一次 TLS 握手)
  3. 发送 HTTP 请求
  4. 服务器响应 HTML
  5. 解析 HTML 建 DOM,并行请求 CSS / JS
  6. CSSOM + DOM → 渲染树
  7. 布局 Layout → 绘制 Paint → 合成 Composite 上屏
  8. 加载后续资源、执行 JS、绑定交互

串起来就是:

URL 地址解析(DNS 解析)→ TCP 连接 → HTTP 请求响应 → 解析 HTML 构建 DOM 树 → 解析 CSS 构建 CSSOM → 生成渲染树 → 布局 Layout(重排 reflow)→ 绘制 Paint(重绘 repaint)→ 分层合成整个界面 → 展示页面

🎤 口述背诵版 ​

先 DNS 找 IP,再握手、发请求拿 HTML。HTTPS 还要多一次 TLS 握手。

接着解析 HTML 建 DOM,解析 CSS 生成 CSSOM,两者合成渲染树;同时并行拉 CSS / JS。

然后布局(重排)算位置大小,绘制(重绘)填像素,分层合成上屏;再执行 JS、绑交互。

重排和重绘的区别?如何优化? ​

概念 ​

  • 重排(Layout / reflow):元素几何信息(位置、宽高、布局)发生改变,浏览器需要重新计算页面上元素的布局位置。重排一定会触发重绘,开销大,性能代价高。
  • 重绘(Paint / repaint):元素样式改变,但不改变布局几何信息,只重新绘制像素(颜色、背景、文字颜色等)。只改外观,不改动位置大小,开销比重排小。
  • 合成(Composite):使用 transform、opacity,直接在 GPU 图层做变换,不触发重排、不触发重绘,性能最好。

触发场景举例 ​

触发重排(同时也会重绘):

  • 修改:width、height、margin、padding、top、left、display
  • 获取 offsetTop / offsetWidth / clientWidth 等布局属性,也会触发强制重排

只触发重绘:

  • 修改:color、background-color、box-shadow,不改变宽高位置

只触发合成:

  • transform、opacity

两者核心区别 ​

  • 重排:重新计算布局几何;重绘:只绘制像素,不计算布局
  • 重排必然引发重绘;重绘不会引发重排
  • 重排性能开销远大于重绘

优化手段 ​

减少重排次数:

  • 避免频繁操作 DOM;DOM 操作先离线处理(DocumentFragment,或先 display: none 改完再显示),一次性渲染到页面
  • 不要在循环里频繁读取布局属性(offsetWidth、clientHeight),读写交替会触发强制同步重排;尽量读放一起、写放一起

使用 CSS 属性优先选择触发合成的属性:

  • 动画优先用 transform、opacity,不要改 top / left

开启 GPU 分层:

  • will-change: transform; 提示浏览器提前做图层提升(不要滥用)

减少频繁重绘:

  • 避免短时间大量修改颜色、阴影这类会触发重绘的样式

虚拟列表:

  • 大数据长列表只渲染可视区域 DOM,减少 DOM 数量,降低重排重绘压力

🎤 口述精简版 ​

简单说,重排是布局变了——宽高、位置一改,浏览器得重新算一遍几何;重绘是样子变了——颜色、背景这些,布局没动,只是把像素重新画一遍。

关系上记住三句:重排一定会带着重绘;重绘不会反过来触发重排;性能上重排最贵,重绘次之,最好是只走合成。

优化也按这个来:少折腾 DOM,读写布局属性分开别穿插;动画尽量用 transform、opacity,走合成别动布局;列表太长就上虚拟列表,少渲染 DOM。

浏览器缓存机制:强缓存 vs 协商缓存? ​

浏览器拿到资源会先找本地有没有可用缓存。 按「先强缓存、再协商缓存」这条线讲。

强缓存:有效期内直接用本地,不再问服务器 ​

命中强缓存时,不会向服务器发请求(Network 里常见 from disk / memory cache)。

靠响应头告诉浏览器「能用多久」:

  • 现在主流:Cache-Control: max-age=秒数(相对时间,从收到响应算起)
  • 老写法:Expires(绝对过期时间)
  • 两个都有时,以 Cache-Control 为准

未过期 → 直接用本地;过期了 → 进入协商缓存。

协商缓存:带「上次的指纹」去问一句,变没变 ​

强缓存失效后,浏览器还会发请求,但会带上上次缓存的标识,让服务器判断资源有没有改:

服务端当初给的浏览器再请求时带的怎么比
ETag(内容指纹)If-None-Match精确,内容变了指纹就变
Last-Modified(上次修改时间)If-Modified-Since粗一点,按时间
  • 没变 → 返回 304 Not Modified,正文几乎不传,继续用本地缓存
  • 变了 → 返回 200 + 新内容,并更新本地缓存

两个标识都能用时,一般 ETag 优先(更准)。

串起来的流程 ​

请求资源 → 强缓存未过期?直接用本地(不发包) → 过期了 → 带 ETag / 修改时间去问 → 304 用旧的 / 200 换新的。

🎤 口述精简版 ​

先看强缓存:Cache-Control: max-age 没过期就本地直接用,不问服务器。过期了再协商:带上 ETag 或上次修改时间问服务端变没变,没变回 304 继续用本地,变了回 200 换新的。

GET 与 POST 的区别(不只是传参长度)? ​

  • 语义:GET 取数据、POST 提交
  • GET 参数在 URL(有长度 / 历史 / 明文限制、可被缓存);POST 在 body(更安全、体量大)
  • GET 幂等、可缓存;POST 非幂等
  • 本质都是 HTTP 方法,底层都能带 body / 参数,区别主要在约定与语义

🎤 口述精简版 ​

GET 是「取」、可缓存幂等、参数在 URL;POST 是「交」、放 body、非幂等;别只背长度区别。

HTTP 常见状态码? ​

  • 2xx 成功:200 / 201 / 204
  • 3xx 重定向:301 永久 / 302 临时 / 304 协商缓存
  • 4xx 客户端错:400 参数错 / 401 未认证 / 403 禁止 / 404 不存在 / 405 方法不允许
  • 5xx 服务端错:500 内部 / 502 网关坏 / 503 过载 / 504 超时

🎤 口述精简版 ​

2 成功、3 重定向(304 是缓存)、4 你错了、5 服务器崩了。

HTTP 与 HTTPS 的区别? ​

HTTPS = HTTP + TLS/SSL 加密;HTTP 明文、端口 80、易被窃听篡改;HTTPS 端口 443、有证书鉴权与加密,防中间人。代价:多了一次 TLS 握手开销(可用 HTTP/2、会话复用缓解)。

🎤 口述精简版 ​

HTTPS 就是给 HTTP 套了层 TLS 加密,防窃听防篡改,端口 443,多了次握手开销。

TCP 和 UDP 的区别?三次握手、四次挥手干什么? ​

都是传输层协议。HTTP / HTTPS / WebSocket 走 TCP;DNS 查询、直播、游戏同步常走 UDP。

TCPUDP
连接面向连接,先握手再建无连接,拿起就发
可靠有确认、重传、保序尽最大努力送达,可能丢、乱序、重复
速度慢一点(握手 + 确认)快、头开销小
场景网页、接口、文件、聊天通道DNS、音视频、游戏状态

三次握手(建立连接) ​

目的:双方都确认「我能发、你能收」,避免对着一个已失效的请求白建连接。

  1. 客户端 → SYN:我想连
  2. 服务端 → SYN + ACK:收到了,我也想连
  3. 客户端 → ACK:确认,开始传数据

前面「输入 URL」里的 TCP 连接,指的就是这一步;HTTPS 还要再做一次 TLS 握手。

四次挥手(断开连接) ​

关闭是单向的:我发完了,你那边可能还有数据要发,所以要四次。

  1. 主动方 → FIN:我发完了
  2. 对方 → ACK:知道了
  3. 对方发完 → FIN:我也发完了
  4. 主动方 → ACK:断开

🎤 口述精简版 ​

TCP 可靠、要握手,网页和接口都走它;UDP 不管丢不丢、图快,DNS、直播、游戏常用。三次握手是双方确认都能收发;四次挥手是因为关连接是半关的,另一边可能还有数据。

WebSocket 是什么?和 HTTP、TCP 什么关系? ​

WebSocket 是应用层协议,底层仍走 TCP(wss 再套 TLS)。用来做浏览器里的长连接、全双工:连上之后服务端也能主动推,不用前端一遍遍轮询。

怎么建连 ​

先发一个特殊的 HTTP 请求升级协议,服务端回 101 Switching Protocols,这条 TCP 连接就从 HTTP 变成 WebSocket,之后按帧互发,不再是「一问一答」。

关键请求头:Upgrade: websocket、Connection: Upgrade。

和 HTTP 比 ​

HTTPWebSocket
交互客户端请求,服务端才响应两边随时推
连接一次请求一次响应(Keep-Alive 也是请求驱动)握手后一直挂着
开销每次都带完整头连上后帧头很小
场景拉页面、调接口、提交表单聊天、通知、协作、行情

关系记三层:TCP 负责可靠传输 → HTTP 用来完成一次升级握手 → 之后这条 TCP 上跑的是 WebSocket 帧。它不是 UDP,也不是「替代 TCP」。

前端:new WebSocket('wss://...'),听 onmessage / onclose。业务里通常要做心跳和断线重连。浏览器对 WebSocket 也看 Origin,跨域仍要服务端放行。

🎤 口述精简版 ​

WebSocket 是长连接双向通道,底层还是 TCP。先用 HTTP 带 Upgrade 握手,服务端回 101 就升级成功,之后两边都能推。HTTP 适合一问一答,实时推送用 WebSocket,别靠轮询硬刷。

前端路由:Hash 和 History 有什么区别?实现原理? ​

SPA(单页应用)切页时不会整页刷新,靠前端路由改 URL、换组件。Vue Router 对应 createWebHashHistory 和 createWebHistory。 抓住:URL 长什么样、刷新找不找服务器、和 SEO 的关系;再能讲清实现就三步。

实现原理(两种模式共用一套骨架) ​

前端路由不是服务器换页面,是 JS 自己做这三件事:

  1. 拦住跳转:点 <a> 时 preventDefault,不让浏览器按传统方式去要一份新 HTML
  2. 改地址栏:只改 URL,不刷新文档
  3. 匹配并渲染:用当前 path 去路由表里找组件,渲到 router-view 上

前进 / 后退靠浏览器历史栈。首次打开或刷新时,页面从服务器拿到 index.html,JS 启动后再读一次当前 URL,走第 3 步。

Hash 模式怎么实现 ​

地址类似 https://a.com/#/about。# 后面叫哈希片段(hash),不会发给服务器。

  • 切页:改 location.hash(例如 #/about)
  • 听 hashchange 事件,再匹配路由、换组件
  • 刷新:浏览器只请求 # 前面那一段,拿到的还是 index.html,JS 再读 hash 渲对应页

优点:部署简单,刷新也不用服务器配合。缺点:URL 带 #;搜索引擎基本不把 hash 当独立页面,不利于 SEO。

History 模式怎么实现 ​

地址类似 https://a.com/about。用浏览器 History API:

  • 切页:history.pushState(...) 改路径(不刷新、也不会自动触发 popstate,所以改完要自己渲染)
  • 点后退 / 前进:听 popstate,再按 location.pathname 匹配渲染
  • 替换当前记录用 replaceState(登录后丢掉登录页这类场景)

优点:URL 像真实路径,利于 SEO、也方便预渲染。缺点:用户刷新或直接打开 /about 时,浏览器会向服务器要这个路径。没有这个文件就会 404,需要 Nginx 等做成:找不到文件就回退到 index.html,交给前端路由。

HashHistory
改 URLlocation.hashhistory.pushState
监听变化hashchangepopstate(只覆盖前进后退;pushState 要自己渲)
刷新 / 直开服务器看不到 hash,一般不 404必须服务器回退到 index.html,否则 404
SEO差(多条路由像同一页)更好(每条是独立路径)

⚠️ 关键点:pushState 只改地址栏和历史栈,不发请求、不刷新、不自动触发 popstate。所以 History 模式里「点菜单」要:改 URL + 立刻自己匹配渲染;「点返回」才走 popstate。

🎤 口述精简版 ​

前端路由三步:拦住 a 标签默认跳转、改 URL、按 path 换组件。Hash 改 # 后面那段,听 hashchange,片段不给服务器,部署省事但 SEO 差。History 用 pushState 改真路径,前进后退听 popstate;刷新要服务器把路由都回落到 index.html,不然 404。官网要收录就用 History。

什么是 CDN?它怎么加速? ​

CDN 把资源缓存到离用户近的边缘节点,请求就近返回,降低延迟和源站压力。配合缓存策略(文件名 hash + 强缓存)效果最佳。

🎤 口述精简版 ​

CDN 就是把资源复制到离用户近的节点,就近返回,又快又减负。

前端怎么做错误监控? ​

  • window.onerror / error 事件捕获 JS 错误
  • unhandledrejection 抓 Promise 异常
  • 框架层(Vue errorHandler)兜底
  • 上报到监控平台(Sentry 等)
  • 结合 sourcemap 还原压缩代码位置

🎤 口述精简版 ​

全局 error / unhandledrejection 兜住异常,框架 errorHandler 兜底,配 sourcemap 上报到 Sentry 这类平台。