Capo.js:你的排序对了吗?一行代码检测出来
GitHub: https://github.com/rviscomi/capo.js
npm: @rviscomi/capo.js
Star: 1.1K
协议: Apache-2.0
官网: https://rviscomi.github.io/capo.js/
发布平台: 程序员茄子(chenxutan.com)
标签: 前端性能, head排序, 性能优化, 零依赖, Chrome扩展
引言
<head> 里的元素顺序会影响页面性能,这事儿不少人都知道。
但真要问具体该怎么排,估计没几个人能说清楚。
meta charset应该放最前面?preconnect要在stylesheet之前?async script比defer script优先级高?
Capo.js 就是帮你检测 <head> 排序是否合理的工具。
一、项目概览
基本信息
| 指标 | 数据 |
|---|---|
| Star | 1.1K |
| 协议 | Apache-2.0 |
| npm 周下载 | 4.3 万 |
| 最新版本 | 2.1.0 |
| 文件大小 | 20 kB(Gzip 6 kB) |
| 依赖 | 零依赖 |
| 兼容性 | Node.js / Browser |
| 更新状态 | 活跃中 |
核心思路
来自 Harry Roberts 的 ct.css 研究。
Capo.js 给 <head> 里的每类元素设定了权重,从高到低排列。权重高的应该排在前面,低权重的元素出现在高权重前面,就会被标记为排序违规。
二、权重体系
11 级权重
| 权重 | 类型 | 说明 |
|---|---|---|
| 10 | META | charset、viewport、关键 http-equiv |
| 9 | TITLE | 页面标题 |
| 8 | PRECONNECT | DNS 预连接 |
| 7 | ASYNC_SCRIPT | 异步脚本 |
| 6 | IMPORT_STYLES | @import 样式 |
| 5 | SYNC_SCRIPT | 同步脚本 |
| 4 | SYNC_STYLES | 同步样式表 |
| 3 | PRELOAD | 预加载资源 |
| 2 | DEFER_SCRIPT | 延迟脚本 |
| 1 | PREFETCH_PRERENDER | 预获取/预渲染 |
| 0 | OTHER | 其他元素 |
排序原则
权重高的排前面,权重低的排后面。
违反这个原则就是排序违规。
三、安装方式
1. npm 安装
npm i @rviscomi/capo.js
导入:
// ESM
import { analyzeHeadWithOrdering, BrowserAdapter } from '@rviscomi/capo.js'
// CommonJS
const { analyzeHeadWithOrdering, BrowserAdapter } = require('@rviscomi/capo.js')
2. 浏览器端引入
<script type="module">
import { analyzeHeadWithOrdering, BrowserAdapter } from
'https://cdn.jsdelivr.net/npm/@rviscomi/capo.js@2.1.0/src/index.js'
</script>
3. Chrome 扩展(最方便)
安装 Capo Chrome 扩展,打开任意页面后查看 DevTools 控制台就能看到分析结果。
零代码改动,装上就能用。
四、实战示例
示例1:检测糟糕的 head 排序
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- 故意写一个排序混乱的 head -->
<script src="https://cdn.jsdelivr.net/npm/lodash@4/lodash.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css">
<title>糟糕的 head 排序</title>
<link rel="preconnect" href="https://cdn.jsdelivr.net">
<script src="https://cdn.jsdelivr.net/npm/analytics.js" async></script>
<link rel="preload" href="https://example.com/font.woff2" as="font" crossorigin>
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js" defer></script>
<base href="/">
<link rel="prefetch" href="https://example.com/next-page">
<style>body { font-family: sans-serif; }</style>
</head>
分析代码:
import { analyzeHeadWithOrdering, BrowserAdapter } from
'https://cdn.jsdelivr.net/npm/@rviscomi/capo.js@2.1.0/src/index.js'
const adapter = new BrowserAdapter()
const result = analyzeHeadWithOrdering(document.head, adapter)
// 违规摘要
console.log('违规数:', result.orderingViolations.length)
result.orderingViolations.forEach(v => console.log(v.message))
示例2:正确的 head 排序
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- 按权重从高到低规范排列 -->
<base href="/">
<title>规范的 head 排序</title>
<link rel="preconnect" href="https://cdn.jsdelivr.net">
<script src="https://cdn.jsdelivr.net/npm/analytics.js" async></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4/lodash.min.js"></script>
<style>body { font-family: sans-serif; }</style>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css">
<link rel="preload" href="https://example.com/font.woff2" as="font" crossorigin>
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js" defer></script>
<link rel="prefetch" href="https://example.com/next-page">
</head>
分析结果:
console.log('排序违规数:', result.orderingViolations.length) // 0
五、排序违规的影响
性能影响是真实存在的
| 元素位置错误 | 影响 |
|---|---|
| meta charset 不在第一位 | 浏览器需要重新解析文档 |
| preconnect 太靠后 | DNS 预连接延迟,关键资源加载变慢 |
| sync script 在 style 之前 | 阻塞样式渲染 |
| async script 在 preconnect 之前 | 预连接没生效就加载脚本 |
核心问题
<head>排序对性能的影响是真实存在的,尤其是meta charset和preconnect的位置,搞错了可能导致不必要的阻塞。
六、适用场景
| 场景 | 使用方式 |
|---|---|
| 日常开发 | Chrome 扩展,装上就能用 |
| 自动化检测 | 程序化 API |
| CI 集成 | 集成到 CI 流程 |
| 性能审计 | Lighthouse 辅助工具 |
| 代码审查 | PR 检测 |
七、API 详解
核心方法
analyzeHeadWithOrdering(headElement, adapter)
返回值
| 字段 | 说明 |
|---|---|
| orderingViolations | 排序违规列表 |
| orderingViolations[].message | 违规描述 |
适配器
| 适配器 | 环境 |
|---|---|
| BrowserAdapter | 浏览器环境 |
八、为什么需要这个工具
痛点
<head>排序容易被忽略- 排序规则不直观
- 排序错误难以发现
- 影响是隐性的(性能损耗)
Capo.js 的价值
把一个容易被忽略的优化点给量化了。
九、与其他工具对比
| 工具 | 定位 | 侧重点 |
|---|---|---|
| Capo.js | <head> 排序检测 | 精确、量化 |
| ct.css | CSS 性能诊断 | Harry Roberts 原始研究 |
| Lighthouse | 综合性能审计 | 广而不深 |
| WebPageTest | 页面加载分析 | 全链路 |
十、总结
核心价值
| 价值 | 说明 |
|---|---|
| 零依赖 | 6 kB Gzip |
| 11 级权重 | 量化排序规则 |
| Chrome 扩展 | 装上就能用 |
| 程序化 API | 适合 CI 集成 |
| 量化分析 | 把隐性优化点变成数字 |
推荐理由
日常开发用 Chrome 扩展,自动化用程序化 API。一个被忽略的优化点,一行代码就能检测出来。
本文首发于「程序员茄子」博客,原文链接:https://chenxutan.com