oekazuma/svelte-vitals
GitHub: oekazuma/svelte-vitals
svelte-vitals 是一款面向 SvelteKit 的静态 SEO 检查器,在 CI/PR 阶段无需浏览器即可分析路由的 head 元数据完整性。
Stars: 0 | Forks: 0
# svelte-vitals
[](https://github.com/oekazuma/svelte-vitals/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/svelte-vitals)
[](https://www.npmjs.com/package/svelte-vitals)
[](https://opensource.org/licenses/MIT)
```
npx svelte-vitals
```
## 为什么使用
如果 ESLint 检查的是你 **代码** 的质量,那么 svelte-vitals 检查的就是你 **应用** 的质量——具体来说,即你的路由是否符合 SEO 标准。
| | 检查对象 | 何时检查 | 需要浏览器 |
| ----------------------------------- | ----------------------------------- | --------------------- | --------------- |
| Lighthouse / unlighthouse | 渲染结果(DOM,真实指标) | 部署后 | 是 |
| eslint-plugin-svelte / svelte-check | 语法、类型、部分 a11y | 编码时 | 否 |
| **svelte-vitals** | head 元数据的编写方式 | 构建前/构建期间 | **否** |
它 **不是** Lighthouse 的替代品——它是一个 **上游检查**,能在 CI 或 PR 中发现 SEO 损坏,远早于任何内容进入生产环境。而且尽管名字如此,它 **并不** 测量运行时的 Core Web Vitals (LCP / CLS / INP)。
## 用法
在任何 SvelteKit 项目中运行它:
```
npx svelte-vitals # analyze the current directory
npx svelte-vitals ./apps/web # or a specific path
```
输出示例:
```
Svelte Vitals · SEO (static mode)
Critical (1)
────────────────────────
✗ SEO001 Missing
/none
src/routes/none/+page.svelte
Passed (3)
────────────────────────
✓ SEO001 /blog
✓ SEO001 ↯ dynamic /dynamic
✓ SEO001 /static
↯ = set dynamically (verified at runtime).
```
### 原生 Agent 输出
`svelte-vitals --reporter agent` 会生成一份 Markdown 修复文档,AI 编程 agent 可以直接据此执行操作:每个失败的发现都会列出其位置、具体的修复方案(包含代码片段)以及验收检查。
当在已知的 AI agent 框架(例如 Claude Code 会设置 `CLAUDECODE`)中运行时,它会 **自动** 被选中。你可以在任何地方通过 `SVELTE_VITALS_REPORTER=agent` 强制启用它,或者使用 `--reporter console|json` 覆盖。当被自动选中(而非明确请求)时,stderr 会打印一行提示说明如何覆盖,这样在 agent 终端中运行它的人类用户就不会对 Markdown 输出感到惊讶。
### GitHub 集成
**内联 PR 注释(零配置)。** 在 GitHub Actions 下,svelte-vitals 会自动选择 `github` reporter,发出工作流命令,GitHub 会将这些命令转化为 PR 差异和工作流运行注释中的内联注释:
```
- run: npx svelte-vitals
```
如果你希望在 CI 中得到不同的输出,请使用 `--reporter console|json|sarif`(或 `SVELTE_VITALS_REPORTER`)进行覆盖。
**代码扫描(安全选项卡)。** 生成 SARIF 并上传它,以将发现的问题显示为持久的代码扫描警报。上传操作需要 `security-events: write` 权限,因此请在作业(或工作流)级别授予该权限:
```
jobs:
seo:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- run: npx svelte-vitals --reporter sarif > svelte-vitals.sarif
continue-on-error: true
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: svelte-vitals.sarif
```
`--reporter sarif` 会将 SARIF 2.1.0 写入 stdout;将其重定向到文件以进行上传。
### 开发覆盖层(请求驱动)
在开发过程中获取 SEO 反馈:将开发 handle 添加到 `src/hooks.server.ts`,svelte-vitals 会在你导航时分析每个页面 **渲染后** 的 ``,并将当前路由的警告打印到你的开发服务器终端。它看到的是真实值,因此动态路由(`{data.title}`)会根据实际渲染的内容进行检查。
```
// src/hooks.server.ts
import { sequence } from '@sveltejs/kit/hooks';
import { svelteVitalsHandle } from '@svelte-vitals/vite/hooks';
export const handle = sequence(svelteVitalsHandle());
```
它仅在 `dev` 模式下运行(在生产构建中为 no-op),且从不修改响应——它只读取渲染的 HTML。覆盖范围随导航而动:只有当你访问某个路由时才会对其进行检查,并且仅在其发现的问题发生变化时才再次发出警告。
`svelteVitalsHandle` 接受插件选项中经过精简的一部分——`metaComponents` 和针对每个规则的 `rules` 覆盖(例如 `svelteVitalsHandle({ rules: { SEO008: 'off' } })`)。分析错误会被吞掉(忽略),因此工具的 bug 永远不会破坏请求;在调试时可以设置 `SVELTE_VITALS_DEBUG` 环境变量,以便在终端中显示这些错误。
### 退出代码
| 代码 | 含义 |
| ---- | --------------------------------------------------------------- |
| `0` | 无失败的发现 |
| `1` | 存在严重发现 |
| `2` | 执行错误(不是 SvelteKit 项目、内部错误等) |
这使得 svelte-vitals 可以用作 CI 的门控。
## 工作原理
svelte-vitals 通过遍历布局链(`+layout.svelte` → … → `+page.svelte`)并使用官方的 `svelte/compiler` 解析 ``,来解析每个路由的 **有效 ``**。
其核心设计目标是 **零漏报**。SvelteKit 的元数据通常是动态的,因此每个标签都在两个独立的维度上被检测:
- **存在性** — `own`(由路由设置)、`inherited`(来自父布局)或 `none`
- **取值** — `static`(字面量)、`dynamic`(`{data.title}` — 值仅在运行时可知)或 `absent`(存在但为空)
像 `{data.title} ` 这样的动态标题——这是 SvelteKit 中最常见且正确的模式——**永远不会** 被标记为缺失。它会以 `↯` 标记通过。只有真正缺失(`none`)或为空(`absent`)的元数据才会被扣分。
## 路线图
该项目沿着两个轴线推进:**模式成熟度** 和 **类别覆盖率**。SEO 是第一个类别;随后会有更多类别。
**已发布**
- **静态模式 (CLI)** — 零配置的 `npx svelte-vitals`:解析每个路由的有效 ``,运行 SEO001–SEO009 规则,按路由和全站进行评分,并通过退出代码控制 CI。
- **插件模式** (`@svelte-vitals/vite`) — 搭载 `vite build` 并分析预渲染 HTML 的 ``。与库无关且精确;为成熟的站点提供真实价值。
- **Agent 与 CI 集成** — `console`、`json`、`agent`(Markdown 修复文档)、`sarif`(GitHub 代码扫描)和 `github`(内联 PR 注释)reporter。`agent` reporter 会在 AI agent 框架下自动选择;`github` 会在 GitHub Actions 下自动选择。
**即将推出**
- **开发覆盖层** ([#9](https://github.com/oekazuma/svelte-vitals/issues/9)) — 通过 `transformPageChunk` 在开发时进行原地警告,以便在访问页面时能看到带有真实值的动态路由。
- **`--fix` 自动修复** ([#11](https://github.com/oekazuma/svelte-vitals/issues/11)) — 生成/修复可修复的发现(`robots.txt`、`sitemap.xml`、canonical)。
- **MCP 服务器** ([#24](https://github.com/oekazuma/svelte-vitals/issues/24)) — 将 svelte-vitals 作为 Model Context Protocol 工具公开,以便 agent 可以在其循环中直接调用它。
- **更多类别** ([#10](https://github.com/oekazuma/svelte-vitals/issues/10)) — 性能、可访问性和升级检查,最终在 `1.0` 版本中汇总为一份综合健康报告。
查看设计文档以了解完整的愿景。
## 包
| Package | 描述 |
| ---------------------------------------- | ----------------------------------------------------------- |
| [`svelte-vitals`](./packages/cli) | CLI + 静态模式 (`npx svelte-vitals`) |
| [`@svelte-vitals/core`](./packages/core) | 与运行时无关的核心:类型、规则引擎、评分器、reporter |
| [`@svelte-vitals/vite`](./packages/vite) | 插件模式(构建时):分析预渲染的 `` |
## 开发
这是一个 pnpm-workspaces monorepo (TypeScript / ESM)。
```
pnpm install
pnpm build # build all packages (tsup)
pnpm test # vitest
pnpm typecheck # tsc --noEmit
pnpm lint # prettier --check + eslint
```
版本发布通过 [Changesets](https://github.com/changesets/changesets) 管理:运行 `pnpm changeset` 来描述你的更改,随后合并到 `main` 分支会自动打开发布 PR。
## 许可证
[MIT](./LICENSE.md) © [Kazuma Oe](https://github.com/oekazuma)
标签:MITM代理, SEO检查, SvelteKit, 云安全监控, 图数据库, 自动化攻击, 静态分析