今天,我们很高兴地宣布 Astro 对服务器端渲染 (SSR) 的实验性支持。通过 Astro 中的 SSR,我们解锁了以前不可能实现的全新用例(例如电子商务)和规模。我们的 SSR 实现将 Astro 独特的服务器优先方法与用户认证、登录流程、数据库访问、数据获取等动态功能结合起来。
如果您已准备好开始,请前往文档查阅并开始使用。
动机
我们听到您的声音了!我们最常收到的问题之一是:“Astro 能否进行 SSR?”
当我们着手构建 Astro 时,我们决定专注于预构建的静态站点架构,通常称为“Jamstack”(也称为静态站点生成或 SSG)。这种方法使我们能够快速迭代和推出新功能,但也伴随着一些重要的限制
- 大型站点无法预渲染为静态 HTML,否则会导致更长的构建时间或更慢的客户端动态内容渲染。
- 动态站点无法预渲染为静态 HTML,否则在数据更改时,您将被迫重建和重新部署部分站点。
- 交互式站点无法预渲染为静态 HTML,否则需要将所有用户个性化数据移动到客户端。当您处理静态预构建的 HTML 时,用户名、头像和权限都会变得更加复杂。
电子商务尤其受到上述三个问题的影响。在一个加载性能每一毫秒都至关重要的行业中,如何在没有限制的情况下获得静态 HTML 的出色性能?
从第一天起,我们就知道 Astro 的岛屿架构方法在解决这个问题上具有独特的优势。岛屿允许页面快速加载并延迟变得可交互;用户可以更快地看到页面最重要的部分并与之互动。
隆重推出:服务器端渲染 (SSR)
服务器端渲染是一个众所周知的解决方案,用于扩展大型网站,其历史可以追溯到互联网的早期。SSR 并非万灵药,但如果做得好,对于某些用例来说,SSR 是一个宝贵的工具。
以用户认证为例。使用静态站点生成时,您有几种不同的方法:
-
检查 localStorage 中是否存在 cookie 或 JWT,如果用户没有则重定向到登录页面。如果使用 cookie,这将阻止使用
HttpOnly
,使您容易受到恶意 JavaScript 攻击。<script>if (!parseCookie(document.cookie).auth) {window.location = "/login"}</script>此外,如果令牌无效,您该怎么办?在这种情况下,您仍然需要检查并做出响应。
-
调用一个 API 来检查用户是否已登录,例如
/api/auth
。走这条路意味着在等待响应时,您需要在每个岛屿中显示加载指示器。function App() {const auth = useAuth()if (auth.loading) return <AnnoyingLoadingSpinner />if (!auth.loggedIn) return <LoginPage />return <UserProfile user={auth.user} />}
无论您采用哪种方法,客户端认证始终意味着:
- 如果禁用 JavaScript,则无法运行。
- 您的服务器只能响应
200 OK
状态码。 - 这简直太慢了。用户必须等待完整的 HTML 响应(包括 JS、CSS 等),即使他们随后立即重定向。这会在用户到达正确页面之前创建多个页面请求。
Astro SSR:旨在简化
Next.js、Nuxt、Gatsby、SvelteKit 以及所有现代 JavaScript 元框架都对 SSR 有所了解。那么 Astro SSR 有何特别之处呢?
与我们之前处理 SSR 的当前专注于 JavaScript 的元框架相比,Astro 具有一个关键优势:Astro 从设计之初就旨在运行在服务器上。
使用 Astro,您可以自由地按照自己的想法编写服务器代码,摆脱其他“通用”SPA 优先框架带来的不必要抽象。虽然 SPA 优先的思维可能非常适合超有状态的 Web 应用程序(例如仪表板、应用程序、门户),但对于大多数以内容为中心的网站来说,这是一笔不划算的开销。
以下是 Astro SSR 中用户认证的工作方式,只需 5 行 JavaScript 代码:
---// In an Astro component (*.astro), you write server code directly// in the component front matter (this space between the two --- fences).
// 1. Import any dependencies (Full support for JavaScript/TypeScript)import { getUser } from "../api/index.js"
// 2. Check that the user token exists and is not malicious.const user = await getUser(Astro.request)
// 3. If no user was found, return a redirect. This instantly// completes the response with the correct status code & headers.if (!user) { return Astro.redirect("/login")}
// 4. If the user is logged in, you can now use the `user` object// right in your page template to show an avatar, name, etc.---
<html> ... <h1>Hello {user.name} 👋</h1> <img src={user.avatar} alt={user.name} /> ...</html>
Astro 前置配置就像一个单一的函数调用,它接收一个请求并返回一个渲染好的模板。由于它是一个函数调用,您可以处理请求、获取要馈送到模板的数据,并在需要时提前退出(例如通过重定向)。
API 路由
Astro 的 HTML 优先 Web 开发方法本身就能让您走得很远,但 Astro 也支持使用您喜欢的框架(如 React)构建交互式 UI。当您为客户端构建时,通常需要端点来在用户和服务器之间读写数据。内置的 API 路由可以满足这一需求。
在 Astro 中,API 路由是 src/pages/
文件夹中的 .js
或 .ts
文件,它接收请求并返回响应。API 路由旨在实现最大灵活性:
- 构建一个用于无 JS 表单提交的表单提交处理器。
- 构建一个用于用户文件提交的上传处理器。
- 构建一个基于 JSON 的 REST API,供客户端与服务器通信。
- 构建一个动态资产路由,以返回任何文件类型,包括图像和视频。
API 路由通过导出一个实现 HTTP 方法的函数来工作。以下是一个保存用户资料的 API 路由示例:
export async function post(params, request) { const profile = await request.json() await saveProfile(profile) return new Response(JSON.stringify({ ok: true }), { status: 200, headers: { "Content-Type": "application/json", }, })}
适配器:随处部署 Astro
现代网络主机对开发者体验设定了高标准。开发者期望框架能与他们偏好的提供商集成,无需过多配置或设置。
当我们构建 Astro SSR 时,我们评估了其他框架解决这个问题的方式。最终,我们决定追随 SvelteKit 和 Remix 的脚步,采纳**可插拔主机适配器**的概念。适配器是简单的、可插拔的集成,可以自动为您喜欢的托管服务配置构建。
适配器模型不仅易于开发者设置,还允许我们支持尽可能多的不同类型的主机,包括:
- 与 Cloudflare 和 Deno Deploy 一起完全在边缘运行。
- 在像 Netlify 和 Vercel 这样的现代开发平台上运行。
- 在 AWS、Azure 和 Google Cloud 上的裸机无服务器函数中运行。
- 在您可以自行部署的 JavaScript 服务器运行时(如 Node.js 和 Deno)上运行。
Astro 中的 SSR 支持仍处于实验阶段。在接下来的两个月里,我们很高兴能与所有主要的托管服务提供商合作,为我们的用户关心的每个平台推出更多适配器和合作关系。如果您是托管服务提供商,并有兴趣为 Astro 构建自己的适配器,请通过 Discord 或电子邮件联系我们:partner@astro.build。
为庆祝这一发布,我们有幸与我们的首发合作伙伴(和官方托管赞助商)Netlify 合作,为 Netlify 平台推出了一款官方的、发布即用的适配器。Netlify 适配器只需一行代码即可将您的 Astro SSR 构建配置为在 Netlify Functions 上运行
import { defineConfig } from "astro/config"import netlify from "@astrojs/netlify/functions"
export default defineConfig({ adapter: netlify(),})
要部署,请运行您的 astro build
命令,然后部署到 Netlify
后续步骤
服务器端渲染目前作为实验性 API 在 Astro 1.0 Beta 版本中提供。此版本专注于提供低级原语和构建基础。
了解更多
- 查阅文档以了解 SSR API。
- 访问我们的Discord 频道获取支持并帮助稳定 API。
- 在Twitter上关注我们,本周晚些时候我们将发布更多关于 SSR 的指南。