资源与资源获取
讲一下资源与资源获取。
#type / howto
#status / evergreen
资源与资源获取
网站、软件、多媒体等一切皆资源。大部分有官网来获取,大部分则需要网盘、magnet-links来获取。
目标
理解 Web 资源的分类、获取流程与优化策略,掌握:
- 各类资源的特点与用途
- 从 URL 到渲染的完整获取链路
- 资源加载优化手段(预加载、懒加载、缓存)
资源分类
| 类型 | 常见格式 | 说明 |
|---|---|---|
| 文档 | HTML, XML, JSON, PDF | 结构化数据与页面内容 |
| 样式 | CSS, SCSS, Less | 页面视觉表现 |
| 脚本 | JS, TS, WASM | 交互逻辑与计算 |
| 图片 | PNG, JPG, SVG, WebP, AVIF | 视觉素材 |
| 字体 | WOFF2, TTF, OTF | 自定义字体 |
| 媒体 | MP4, MP3, HLS | 音视频流 |
| 数据 | CSV, Parquet, protobuf | 结构化数据交换 |
获取流程
完整链路
用户输入 URL
-> DNS 解析(域名 -> IP)
-> TCP / TLS 握手(建立连接)
-> HTTP 请求(GET/POST,携带 Headers)
-> 服务器处理 -> 返回响应(状态码 + Headers + Body)
-> 缓存判断(强缓存 -> 协商缓存 -> 重新请求)
-> 解析与渲染(HTML -> DOM,CSS -> CSSOM -> Render Tree -> Paint)
关键环节
DNS 解析:浏览器缓存 -> 系统缓存 -> 路由器 -> ISP DNS -> 递归查询。使用 DNS prefetch 可提前解析。
缓存策略:
- 强缓存:
Cache-Control: max-age=31536000(命中后不发请求) - 协商缓存:
ETag/Last-Modified(发请求确认是否更新)
HTTP 版本演进:
- HTTP/1.1:持久连接,但有队头阻塞
- HTTP/2:多路复用,头部压缩,服务器推送
- HTTP/3:基于 QUIC,解决 TCP 队头阻塞
预加载策略
preload
当前页面立即需要的资源,浏览器提前加载:
<link rel="preload" href="/fonts/main.woff2" as="font" crossorigin>
<link rel="preload" href="/css/critical.css" as="style">
prefetch
下一页可能需要的资源,空闲时加载:
<link rel="prefetch" href="/next-page.js">
preconnect
提前建立与第三方源的连接:
<link rel="preconnect" href="https://cdn.example.com">
<link rel="dns-prefetch" href="https://analytics.example.com">
对比
| 指令 | 优先级 | 时机 | 用途 |
|---|---|---|---|
| preload | 高 | 当前页面立即加载 | 关键 CSS/字体/脚本 |
| prefetch | 低 | 空闲时加载 | 下一页资源 |
| preconnect | 中 | 提前握手 | 第三方域名 |
资源优化手段
图片优化
<!-- 响应式图片 -->
<img srcset="img-320w.webp 320w, img-640w.webp 640w"
sizes="(max-width: 600px) 320px, 640px"
src="img-640w.jpg"
loading="lazy"
decoding="async">
<!-- 使用现代格式 -->
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="fallback">
</picture>
懒加载
非首屏资源延迟加载:
// 原生懒加载
<img loading="lazy" src="...">
// Intersection Observer 实现
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.src = entry.target.dataset.src
observer.unobserve(entry.target)
}
})
})
代码分割
// 动态导入,按需加载
const module = await import('./heavy-module.js')
验证
- 使用 DevTools Network 面板确认资源加载顺序
- 确认 preload 资源在首屏渲染前完成加载
- 确认图片懒加载在滚动到视口时才发起请求
- 确认强缓存资源(200 from cache)不重复下载
- Lighthouse Performance 评分 > 90
常见问题
Q: preload 的资源没有提前加载?
检查 as 属性是否正确设置。缺少 as 属性时浏览器会以低优先级加载。字体还需加 crossorigin 属性。
Q: 图片格式如何选择?
优先级:AVIF > WebP > JPEG/PNG。使用 <picture> 标签做格式降级。SVG 适合图标和简单图形。
Q: 跨域资源加载失败?
检查 CORS 头配置。字体文件必须设置 crossorigin 属性。CDN 资源需返回 Access-Control-Allow-Origin 头。
Q: 如何判断资源加载性能?
使用 Chrome DevTools 的 Lighthouse 和 Performance 面板。关注 FCP(首次内容绘制)、LCP(最大内容绘制)、TTFB(首字节时间)等指标。