为什么我们在托管比较平台中选择 Astro 而不是 SvelteKit
Source: Dev.to
请提供您希望翻译的文章正文内容,我将按照要求把它翻译成简体中文并保留原有的格式。
为什么我们在托管比较平台上选择 Astro 而不是 SvelteKit
我们正在构建 HostingSift,一个用于并排比较托管服务商的平台——包括价格表、功能细分、筛选器、用户评论等。刚开始时,我们面临一个关键决定:SvelteKit 还是 Astro?
我们选择了 Astro。原因如下。
项目背景
- 内容丰富的网站:23+ 个托管服务提供商简介,每个都有多个套餐、定价层级、功能规格和用户评论。
- 附加页面:对比页面、分类列表、推荐测验和博客。
- 交互部分:按计费周期过滤套餐、切换对比表、认证流程、评论表单。
大多数用户看到的内容是静态的,不需要 JavaScript 渲染。这个比例决定了后续的一切。
我们对 Svelte 的热爱
- Svelte 5 的响应式模型(runes)优雅。
- 开发者体验极佳。
- SvelteKit 成熟、功能完整,具备基于文件的路由、SSR、API 端点和表单操作。
那为什么不直接使用它呢?
核心区别
| Feature | SvelteKit | Astro |
|---|---|---|
| Default behavior | 假设每个页面都是交互式的;会发送一个 JS 包来为每个路由进行 hydration。 | 默认不输出客户端 JavaScript;页面渲染为静态 HTML,除非你主动开启。 |
| Prerendering | 默认服务器渲染;需要时在每个路由上选择 prerender。 | 默认在构建时进行 prerender;需要时选择服务器渲染。 |
| Hydration model | 整个页面作为单一的 hydration 单元。 | “岛屿”模式——各个组件独立 hydrate。 |
这并不是细微的差别;它会改变你构建页面的思路。
Astro 为我们工作的方式
我们使用 .astro 组件(静态 HTML,无 JavaScript)和 Svelte 组件(交互式,带 JavaScript)来构建页面。Svelte 组件会成为 岛屿,独立进行 hydration,而页面的其余部分是纯 HTML,浏览器会立即渲染。
示例:托管配置页面
---
// Import static and interactive components
import Layout from '../../layouts/Layout.astro';
import PlanCard from '../../components/PlanCard.svelte';
import ReviewSection from '../../components/ReviewSection.svelte';
import SpecsTable from '../../components/SpecsTable.astro';
// Fetch data on the server
const { hosting, plans } = await fetchHostingData(slug);
---
{hosting.name}
{hosting.description}
- **每个岛屿自行水合**。如果其中一个失败,页面的其余部分仍然可以工作。
- **静态部分**(布局、描述、规格表、SEO 元数据)不携带 **JavaScript**。
实用决策
- 静态页面(首页、分类页面、法律页面、博客文章)预渲染为纯 HTML 文件——快速、可缓存、每次请求无需服务器计算。
- 需要新鲜数据的页面(带实时定价的托管配置文件、过滤后的列表)标记为服务器渲染。意图明确。
相反,SvelteKit 默认对所有内容进行服务器渲染,并要求你选择性地进行预渲染——这与我们站点最需要的恰恰相反。
我们放弃的内容
| Trade‑off | Details |
|---|---|
| Form actions | SvelteKit 的渐进增强表单很好用。在 Astro 中我们使用 Hono API 并通过客户端 fetch,这导致需要为 onSubmit 处理函数和加载状态添加样板代码。 |
| Learning curve | 开发者必须同时了解 .astro 和 .svelte 文件。每天需要决定某个内容属于静态还是交互式的情况有数十次。 |
| View Transitions | Astro 的过渡在每次导航时都会重新执行内联脚本。我们额外花时间保护 Google Analytics 和 vanilla‑cookie‑consent,以避免重复初始化。SvelteKit 的客户端路由开箱即用地更优雅地处理了这一点。 |
| API layer | SvelteKit 的 +server.ts 提供了紧密集成的 API 路由。我们选择了独立的 Hono 服务器(对未来的移动应用有用),这意味着需要管理两个进程、分别部署以及 CORS 配置。 |
结果
- 主页 JavaScript 负载:约 40 KB 总计。
- 交互部分(提供者网格、新闻通讯表单)是小的、独立的 bundle。
- 在可比的 SvelteKit 设置中,负载会显著更大,因为每个路由都会发送一个 hydration bundle,即使是纯静态内容也是如此。
结论
Astro 并不是 Svelte 的替代品;它是一个组合层,使我们能够在所有交互式组件中保留 Svelte 5,同时以符合内容优先站点的方式处理 路由和页面组合。默认的零 JS 哲学、基于岛屿的水化以及构建时预渲染,使 HostingSift 的决定变得明确。
客户端路由器开销
框架的客户端路由器在我们的任何代码加载之前就增加了基线开销 在我们的任何代码加载之前.
服务器端 OG 图片生成
Astro 的端点模型使 Open Graph 图片生成变得直接:
- 为每个托管资料、比较页面和博客文章生成 动态 OG 图片。
- 使用 Satori(用于 SVG → PNG 转换)和 Sharp(图像处理)构建。
- 实现为标准 API 路由,返回 PNG 缓冲区 —— 无需特殊配置。
// src/pages/api/og-image.ts
import { satori } from 'satori';
import sharp from 'sharp';
export async function GET({ params }) {
const svg = await satori(/* … */);
const png = await sharp(Buffer.from(svg)).png().toBuffer();
return new Response(png, { headers: { 'Content-Type': 'image/png' } });
}
构建时间保持快速
- 预渲染 50+ 静态页面。
- 生成站点地图。
- 编译 Svelte 岛屿。
所有这些在 30 秒以内 完成。添加新提供商几乎不会影响构建,因为大多数步骤是并行运行的。
部署 SvelteKit
“SvelteKit 在理论上可以在任何地方运行。实际上,最顺畅的方式是部署到 Vercel。”
- Vercel:
adapter-auto会自动检测平台;集成非常完善。 - Self‑hosting:可以使用
adapter-node,但你必须自行配置 Vercel 开箱即用的那些设置。
在 Hetzner ARM64 VPS 上自托管
我们的技术栈运行在单个 Hetzner ARM64 VPS 上:
- Astro 站点
- Hono API
- PostgreSQL
- 全部通过 nginx 和 Cloudflare 进行代理
费用: 约 €5 / 月。
部署步骤
# 1️⃣ Install the Node adapter
npm i -D @astrojs/node
# 2️⃣ Build the project
npm run build
# 3️⃣ Run with PM2 (or any process manager)
pm2 start ./dist/server/entry.mjs --name astro-site
没有适配器的怪癖,也没有平台特定的边缘情况——输出的是一个标准的 Node.js 服务器。
成本角度
| 平台 | 定价模型 | 常规专业计划 | 隐性费用 |
|---|---|---|---|
| Vercel / Netlify | 按使用量计费 | $20‑$25 / mo | 函数执行时间、带宽、超额峰值(例如,机器人爬取) |
| 固定费用 VPS | 固定月费 | €5 / mo(Hetzner) | 可预测——流量可翻倍/三倍而账单不变 |
- 托管平台 提供 CI/CD、预览部署、边缘函数、零配置扩展——对不想管理基础设施的团队非常有价值。
- VPS 提供控制权和成本可预测性;扩容只需换更大的机器。
架构概览
- 23 家托管服务提供商,数百个套餐,比较页面,测验,博客,用户认证,管理员面板——全部运行在单台 Hetzner 服务器上。
- 新的提供商简介 = 仅需数据。
- 新的交互功能 = 将新的 Svelte island 插入现有页面。
- 新的静态页面 = 使用 无客户端开销 的
.astro文件。
框架选择
- SvelteKit 能工作吗? 当然可以。对于更像应用的产品(仪表盘、实时协作、繁重的客户端状态),我们会毫不犹豫地选择 SvelteKit。
- 对于内容为先的网站,交互性是例外,使用带有 Svelte 岛屿的 Astro 被证明是正确的选择——并不是因为 SvelteKit 做不到,而是因为 Astro 的默认设置已经指向了我们想要的方向。
要点: 不必与框架“搏斗”本身就有很大价值。Astro 为你提供所需的最小客户端负载,同时仍然可以在需要交互的地方撒入 Svelte。