🔧
全栈框架
22 道题目
难度筛选:
Pages Router(传统):
• 基于
•
•
• 所有组件默认客户端组件
App Router(Next.js 13+):
• 基于
• React Server Components(RSC)支持
•
•
• 内置 Loading、Error、Not Found 等特殊文件
• 支持 Streaming SSR + Suspense
核心差异:
• App Router 默认组件是服务端的(RSC),Pages Router 默认是客户端的
• App Router 的布局不会在导航时重新渲染
• 数据获取方式从
建议:新项目使用 App Router。
• 基于
pages/ 目录的路由•
getServerSideProps(SSR)、getStaticProps(SSG)•
_app.tsx + _document.tsx 包装• 所有组件默认客户端组件
App Router(Next.js 13+):
• 基于
app/ 目录,支持嵌套布局• React Server Components(RSC)支持
•
layout.tsx(不会重新渲染)+ page.tsx•
'use client' 标记客户端组件• 内置 Loading、Error、Not Found 等特殊文件
• 支持 Streaming SSR + Suspense
核心差异:
• App Router 默认组件是服务端的(RSC),Pages Router 默认是客户端的
• App Router 的布局不会在导航时重新渲染
• 数据获取方式从
getStaticProps 变为直接 async/await建议:新项目使用 App Router。
查看答案即标记为已答
RSC(React Server Components):在服务端执行的 React 组件,不会发送 JS 到客户端。
解决的问题:
1. Bundle 体积:服务端组件的依赖不会打包到客户端
2. 直接访问后端:可以直连数据库、文件系统,不需要 API 层
3. 自动代码分割:客户端组件边界自动成为分割点
4. 避免水合开销:服务端组件不需要水合
Server vs Client 组件:
• Server Component:默认,不能使用 useState/useEffect/事件监听
• Client Component('use client'):可使用 Hooks、事件、浏览器 API
示例:
注意:RSC 不是 SSR。SSR 输出 HTML 仍需水合;RSC 输出的是序列化的组件树描述。
解决的问题:
1. Bundle 体积:服务端组件的依赖不会打包到客户端
2. 直接访问后端:可以直连数据库、文件系统,不需要 API 层
3. 自动代码分割:客户端组件边界自动成为分割点
4. 避免水合开销:服务端组件不需要水合
Server vs Client 组件:
• Server Component:默认,不能使用 useState/useEffect/事件监听
• Client Component('use client'):可使用 Hooks、事件、浏览器 API
示例:
// Server Component(默认)
async function Page() {
const data = await db.query('SELECT...'); // 直接访问数据库
return <div>{data.map(...)}</div>;
}注意:RSC 不是 SSR。SSR 输出 HTML 仍需水合;RSC 输出的是序列化的组件树描述。
查看答案即标记为已答
Nuxt.js 3 支持的渲染模式:
1. Universal(SSR + CSR 混合)— 默认:
• 首次请求 SSR,后续导航 CSR
• 最佳 SEO + 交互体验
•
2. SPA(纯客户端):
•
• 适合后台管理等不需要 SEO 的应用
3. SSG(静态生成):
•
• Crawler 自动发现路由,生成静态 HTML
• 支持
4. Hybrid Rendering(混合渲染):
每个路由可以独立设置渲染策略,非常灵活。
1. Universal(SSR + CSR 混合)— 默认:
• 首次请求 SSR,后续导航 CSR
• 最佳 SEO + 交互体验
•
ssr: true(默认)2. SPA(纯客户端):
•
ssr: false• 适合后台管理等不需要 SEO 的应用
3. SSG(静态生成):
•
nuxt generate• Crawler 自动发现路由,生成静态 HTML
• 支持
routeRules 配置混合渲染4. Hybrid Rendering(混合渲染):
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true }, // SSG
'/api/**': { cors: true }, // API
'/blog/**': { swr: 3600 }, // ISR(stale-while-revalidate)
'/admin/**': { ssr: false }, // SPA
}
})每个路由可以独立设置渲染策略,非常灵活。
查看答案即标记为已答
Remix 的核心理念:
• 回归 Web 标准(Request/Response/FormData)
• 数据优先(Loader 加载数据,Action 处理表单提交)
• 渐进增强(即使 JS 不可用,表单仍可提交)
• 嵌套路由 + 并行数据加载
数据加载(Loader):
vs Next.js App Router:
选择:重视 Web 标准和渐进增强选 Remix;生态和社区选 Next.js。
• 回归 Web 标准(Request/Response/FormData)
• 数据优先(Loader 加载数据,Action 处理表单提交)
• 渐进增强(即使 JS 不可用,表单仍可提交)
• 嵌套路由 + 并行数据加载
数据加载(Loader):
export async function loader({ request }) {
const url = new URL(request.url);
const data = await db.users.findMany();
return json({ users: data });
}vs Next.js App Router:
| Remix | Next.js | |
|---|---|---|
| 数据加载 | loader 函数 | Server Component 直接 async |
| 数据变更 | action + FormData | Server Actions |
| 嵌套路由 | 原生支持 | Layout + Template |
| Web 标准 | 深度依赖 | 部分依赖 |
| 离线/无JS | 渐进增强 | 需要 JS |
选择:重视 Web 标准和渐进增强选 Remix;生态和社区选 Next.js。
查看答案即标记为已答
Astro 的核心特点:
1. 零 JS 默认:
组件渲染为纯 HTML,不发送 JS 到客户端。只有标记了指令的组件才会水合。
2. Islands Architecture(岛屿架构):
3. 框架无关:
可以在同一页面使用 React、Vue、Svelte、Solid 等组件
4. 内容驱动:
内置 Markdown/MDX 支持、Content Collections
5. 极致性能:
默认输出纯静态 HTML,Lighthouse 满分常见
适合场景:
• 博客、文档站、营销页面
• 内容为主的网站
• 需要多框架组件共存的场景
不适合:高度交互的 SPA 应用(如后台管理)
1. 零 JS 默认:
组件渲染为纯 HTML,不发送 JS 到客户端。只有标记了指令的组件才会水合。
2. Islands Architecture(岛屿架构):
<ReactCounter client:load /> — 立即水合<ReactCounter client:visible /> — 可见时水合<ReactCounter client:idle /> — 浏览器空闲时水合3. 框架无关:
可以在同一页面使用 React、Vue、Svelte、Solid 等组件
4. 内容驱动:
内置 Markdown/MDX 支持、Content Collections
5. 极致性能:
默认输出纯静态 HTML,Lighthouse 满分常见
适合场景:
• 博客、文档站、营销页面
• 内容为主的网站
• 需要多框架组件共存的场景
不适合:高度交互的 SPA 应用(如后台管理)
查看答案即标记为已答
SvelteKit 的特点:
1. 基于 Svelte:
• 编译型框架(无虚拟 DOM,编译为原生 DOM 操作)
• 极小的 Bundle 体积
• 简洁的语法(响应式声明:
2. 灵活的渲染模式:
• 每个页面可独立设置 SSR/CSR/SSR/Prerender
•
•
3. 文件系统路由:
4. Form Actions:
类似 Remix,原生表单处理,渐进增强
优势:性能极佳、开发体验好、学习成本低
劣势:生态不如 React/Vue、Svelte 5 Rune 有破坏性变更
1. 基于 Svelte:
• 编译型框架(无虚拟 DOM,编译为原生 DOM 操作)
• 极小的 Bundle 体积
• 简洁的语法(响应式声明:
$: 或 Rune:$state)2. 灵活的渲染模式:
• 每个页面可独立设置 SSR/CSR/SSR/Prerender
•
export const ssr = false; → CSR•
export const prerender = true; → SSG3. 文件系统路由:
src/routes/+page.svelte — 页面src/routes/+page.ts — 数据加载(load 函数)src/routes/+server.ts — API 路由4. Form Actions:
类似 Remix,原生表单处理,渐进增强
优势:性能极佳、开发体验好、学习成本低
劣势:生态不如 React/Vue、Svelte 5 Rune 有破坏性变更
查看答案即标记为已答
1. getStaticProps(SSG):
构建时执行,生成静态页面。
2. getStaticPaths(动态路由 SSG):
指定哪些动态路径需要预渲染。
•
•
•
3. getServerSideProps(SSR):
每次请求时执行。
App Router 替代方案:直接在 Server Component 中
构建时执行,生成静态页面。
export async function getStaticProps() {
const data = await fetch('https://api.example.com/posts');
return { props: { posts: data }, revalidate: 60 }; // ISR
}2. getStaticPaths(动态路由 SSG):
指定哪些动态路径需要预渲染。
export async function getStaticPaths() {
const posts = await getAllPosts();
return {
paths: posts.map(p => ({ params: { id: p.id } })),
fallback: 'blocking', // 或 true / false
};
}•
fallback: false — 未列出的路径返回 404•
fallback: true — 未列出的先返回 fallback 页面,后台生成•
fallback: 'blocking' — 未列出的按需 SSR,然后缓存3. getServerSideProps(SSR):
每次请求时执行。
export async function getServerSideProps(context) {
return { props: { data } };
}App Router 替代方案:直接在 Server Component 中
async/await 获取数据。 查看答案即标记为已答
传统 Hydration 问题:必须下载整个页面的 JS 并一次性水合所有组件,导致:
• JS 体积大,下载慢
• 水合执行阻塞主线程
• 交互延迟(TTI 差)
Selective Hydration(选择性水合):
• 优先水合用户正在交互的部分
• React 18 + Suspense 实现
• 不同 Suspense 边界可以独立水合
Progressive Hydration(渐进式水合):
• 页面加载时不立即水合所有组件
• 根据条件逐步激活(如可见时、空闲时、交互时)
• 减少初始 JS 执行量
各框架实现:
• React 18:Suspense + Selective Hydration
• Astro:岛屿架构,通过
• Qwik:Resumability(可恢复性),完全跳过水合,事件处理函数按需下载
趋势:从"全量水合"到"按需水合"到"无水合"。
• JS 体积大,下载慢
• 水合执行阻塞主线程
• 交互延迟(TTI 差)
Selective Hydration(选择性水合):
• 优先水合用户正在交互的部分
• React 18 + Suspense 实现
• 不同 Suspense 边界可以独立水合
Progressive Hydration(渐进式水合):
• 页面加载时不立即水合所有组件
• 根据条件逐步激活(如可见时、空闲时、交互时)
• 减少初始 JS 执行量
各框架实现:
• React 18:Suspense + Selective Hydration
• Astro:岛屿架构,通过
client:visible 等指令控制水合时机• Qwik:Resumability(可恢复性),完全跳过水合,事件处理函数按需下载
趋势:从"全量水合"到"按需水合"到"无水合"。
查看答案即标记为已答
PPR(Partial Prerendering):Next.js 14+ 引入的混合渲染策略,将静态外壳和动态内容块组合在同一个 HTTP 响应中。
核心思路:
• 页面的"外壳"(layout、静态部分)在构建时预渲染为静态 HTML
• 动态内容块通过
• 请求时,立即返回静态外壳,动态部分流式填充
示例:
优势:
• 静态内容 TTFB 极快
• 动态内容不阻塞静态部分
• 一个路由同时享受 SSG + SSR 的优势
• 无需手动配置,基于 Suspense 自动推断
核心思路:
• 页面的"外壳"(layout、静态部分)在构建时预渲染为静态 HTML
• 动态内容块通过
<Suspense> 边界标记• 请求时,立即返回静态外壳,动态部分流式填充
示例:
export default function Page() {
return (
<div>
<Header /> {/* 静态:构建时预渲染 */}
<Suspense fallback={<Skeleton />}>
<DynamicFeed /> {/* 动态:请求时流式渲染 */}
</Suspense>
<Footer /> {/* 静态 */}
</div>
);
}优势:
• 静态内容 TTFB 极快
• 动态内容不阻塞静态部分
• 一个路由同时享受 SSG + SSR 的优势
• 无需手动配置,基于 Suspense 自动推断
查看答案即标记为已答
| Next.js | Nuxt.js | |
|---|---|---|
| 基础框架 | React | Vue |
| 路由 | 文件系统(app/ 或 pages/) | 文件系统(pages/) |
| SSR | ✅ | ✅ |
| SSG | ✅ | ✅(nuxt generate) |
| ISR | ✅ 原生支持 | ✅ 通过 routeRules 的 swr |
| Server Components | ✅(RSC) | ❌(Vue 不支持 RSC) |
| API 路由 | Route Handlers / API Routes | server/api/ 目录 |
| 混合渲染 | Per-page 或 route segment | routeRules 统一配置 |
| 自动导入 | ❌ | ✅(组件、组合式函数自动导入) |
| 模块生态 | 庞大(React 生态) | Nuxt Modules |
选择建议:
• 团队熟悉 React → Next.js
• 团队熟悉 Vue → Nuxt.js
• 需要 RSC → Next.js
• 追求开发体验(自动导入、零配置)→ Nuxt.js
• 两者都是成熟的全栈框架,核心功能差异不大
查看答案即标记为已答
Next.js Middleware:在请求到达页面之前运行的函数,用于拦截、重定向、重写请求。
创建方式:
限定匹配路径:
典型用途:
1. 身份验证/权限检查
2. 国际化重定向
3. A/B 测试
4. 日志/分析
5. Bot 检测
运行环境:Edge Runtime(轻量、快速、有限 API),不是 Node.js。不能使用 fs 等 Node 模块。
创建方式:
// middleware.ts(根目录或 src/)
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const token = request.cookies.get('token');
if (!token) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}限定匹配路径:
export const config = {
matcher: ['/dashboard/:path*', '/admin/:path*'],
};典型用途:
1. 身份验证/权限检查
2. 国际化重定向
3. A/B 测试
4. 日志/分析
5. Bot 检测
运行环境:Edge Runtime(轻量、快速、有限 API),不是 Node.js。不能使用 fs 等 Node 模块。
查看答案即标记为已答
Next.js App Router 的四层缓存:
1. Request Memoization(请求记忆化):
• 同一渲染周期内,相同 fetch 请求只执行一次
• 自动生效,无需配置
2. Data Cache(数据缓存):
• fetch 请求结果持久化到服务端
• 跨请求复用,直到重新验证
•
•
•
3. Full Route Cache(路由缓存):
• 构建时渲染静态路由并缓存
• 静态路由在构建时渲染,动态路由在请求时渲染
4. Router Cache(客户端路由缓存):
• 浏览端缓存已访问路由的 RSC Payload
• 后退/前进不重新请求
• 持续时间:session 内 30s~5min
退出缓存:
•
•
•
1. Request Memoization(请求记忆化):
• 同一渲染周期内,相同 fetch 请求只执行一次
• 自动生效,无需配置
2. Data Cache(数据缓存):
• fetch 请求结果持久化到服务端
• 跨请求复用,直到重新验证
•
fetch(url, { cache: 'force-cache' }) — 缓存(默认)•
fetch(url, { cache: 'no-store' }) — 不缓存•
fetch(url, { next: { revalidate: 60 } }) — ISR3. Full Route Cache(路由缓存):
• 构建时渲染静态路由并缓存
• 静态路由在构建时渲染,动态路由在请求时渲染
4. Router Cache(客户端路由缓存):
• 浏览端缓存已访问路由的 RSC Payload
• 后退/前进不重新请求
• 持续时间:session 内 30s~5min
退出缓存:
•
revalidatePath('/path')•
revalidateTag('tag')•
cookies() / headers() 使路由变为动态 查看答案即标记为已答
Auto-imports:Nuxt 自动导入组件、组合式函数、工具函数,无需手动 import。
1. 组件自动导入:
2. 组合式函数自动导入:
3. Nuxt 内置 API 自动导入:
4. 第三方模块自动导入:
安装 Nuxt 模块后自动注册
原理:Nuxt 在构建时扫描目录,生成
优点:减少样板代码,开发更快;注意:IDE 需要安装 Nuxt 插件才能正确提示。
1. 组件自动导入:
// components/ 目录下的组件自动可用
// components/MyButton.vue → <MyButton />
// components/nav/Header.vue → <NavHeader />2. 组合式函数自动导入:
// composables/ 目录
// composables/useAuth.ts
export const useAuth = () => { ... }
// 页面中直接使用,无需 import
const { user, login } = useAuth();3. Nuxt 内置 API 自动导入:
useState, useFetch, useRouter, useCookie, navigateTo, ...4. 第三方模块自动导入:
安装 Nuxt 模块后自动注册
原理:Nuxt 在构建时扫描目录,生成
.nuxt/imports.d.ts 声明文件,并自动注入 import 语句。优点:减少样板代码,开发更快;注意:IDE 需要安装 Nuxt 插件才能正确提示。
查看答案即标记为已答
Content Collections:Astro 内置的内容管理系统,为 Markdown/MDX 内容提供类型安全和组织结构。
定义集合:
使用集合:
目录结构:
优点:Zod schema 验证 + 类型推导 + 自动 slug + Markdown 增强。
定义集合:
// src/content/config.ts
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
schema: z.object({
title: z.string(),
date: z.date(),
tags: z.array(z.string()),
draft: z.boolean().default(false),
}),
});
export const collections = { blog };使用集合:
// 获取所有文章
const allPosts = await getCollection('blog');
// 渲染单篇文章
const { Content } = await render(entry);目录结构:
src/content/
blog/
first-post.md
second-post.mdx
docs/
getting-started.md优点:Zod schema 验证 + 类型推导 + 自动 slug + Markdown 增强。
查看答案即标记为已答
.astro 文件结构:由 Frontmatter(脚本区)和模板(HTML)两部分组成。
关键特性:
• Frontmatter 在构建时执行,不发送到客户端
• 模板语法类似 JSX 但有一些区别(属性用 kebab-case、不需要根元素包裹)
•
•
---
// Frontmatter(服务端运行)
// 这里写 JS/TS,构建时执行
import Header from '../components/Header.astro';
const title = 'Hello Astro';
const items = ['A', 'B', 'C'];
---
<!-- 模板区:类 JSX 的 HTML -->
<html>
<Header title={title} />
<ul>
{items.map(item => <li>{item}</li>)}
</ul>
</html>
<style>
/* 自动 Scoped CSS */
li { color: blue; }
</style>
<script>
// 仅在客户端执行的 JS
console.log('hello');
</script>关键特性:
• Frontmatter 在构建时执行,不发送到客户端
• 模板语法类似 JSX 但有一些区别(属性用 kebab-case、不需要根元素包裹)
•
<style> 自动作用域隔离(生成唯一 hash 类名)•
<slot /> 支持子内容传入(类似 Vue slot) 查看答案即标记为已答
核心问题:Astro 默认输出纯 HTML(零 JS),交互组件需要通过客户端指令激活。
所有指令:
1. client:load — 页面加载立即水合
适合:立即可见的交互元素(导航栏、登录按钮)
2. client:visible — 进入视口时水合
适合:首屏以下的组件,延迟加载减少初始 JS
3. client:idle — 浏览器空闲时水合
适合:非紧急交互组件(客服浮窗、Cookie 横幅)
4. client:media="(max-width: 768px)" — 匹配媒体查询时水合
适合:仅特定设备需要的组件
5. client:only="react" — 跳过 SSR,仅客户端渲染
适合:依赖浏览器 API 的组件(如图表库)
不加指令 = 纯静态 HTML(零 JS 输出)
所有指令:
1. client:load — 页面加载立即水合
<ReactCounter client:load />适合:立即可见的交互元素(导航栏、登录按钮)
2. client:visible — 进入视口时水合
<HeavyChart client:visible />适合:首屏以下的组件,延迟加载减少初始 JS
3. client:idle — 浏览器空闲时水合
<ChatWidget client:idle />适合:非紧急交互组件(客服浮窗、Cookie 横幅)
4. client:media="(max-width: 768px)" — 匹配媒体查询时水合
<MobileMenu client:media="(max-width: 768px)" />适合:仅特定设备需要的组件
5. client:only="react" — 跳过 SSR,仅客户端渲染
适合:依赖浏览器 API 的组件(如图表库)
不加指令 = 纯静态 HTML(零 JS 输出)
查看答案即标记为已答
View Transitions:Astro 内置的页面切换动画方案,基于浏览器原生 View Transitions API。
启用方式:
工作原理:
1. 用户点击站内链接时,Astro 拦截导航
2. 浏览器对新旧页面截图
3. 自动执行淡入淡出等过渡动画
4. 不需要整页刷新,体验类似 SPA
自定义过渡动画:
指定元素持续存在:
优点:
• 零配置就有 SPA 级别的过渡体验
• MPA 架构(SEO 友好)+ SPA 体验
• 降级方案:不支持的浏览器直接跳转(无动画)
启用方式:
import { ViewTransitions } from 'astro:transitions';
<head>
<ViewTransitions />
</head>工作原理:
1. 用户点击站内链接时,Astro 拦截导航
2. 浏览器对新旧页面截图
3. 自动执行淡入淡出等过渡动画
4. 不需要整页刷新,体验类似 SPA
自定义过渡动画:
<style>
::view-transition-old(root) { animation: fade-out 0.3s; }
::view-transition-new(root) { animation: fade-in 0.3s; }
</style>指定元素持续存在:
<header transition:persist> — 页面切换时 header 不重新渲染优点:
• 零配置就有 SPA 级别的过渡体验
• MPA 架构(SEO 友好)+ SPA 体验
• 降级方案:不支持的浏览器直接跳转(无动画)
查看答案即标记为已答
Astro 三种渲染模式:
1. Static(默认)— 静态站点生成:
• 构建时生成所有 HTML
• 部署到 CDN,零服务器成本
• 适合:博客、文档、营销页
2. Server(SSR)— 服务端渲染:
• 每次请求动态生成页面
• 需要适配器(Node.js / Cloudflare / Vercel / Netlify)
• 适合:用户仪表盘、需要 session 的页面
3. Hybrid(混合)— 按页选择:
或全局
适配器:
•
•
•
•
1. Static(默认)— 静态站点生成:
• 构建时生成所有 HTML
• 部署到 CDN,零服务器成本
• 适合:博客、文档、营销页
2. Server(SSR)— 服务端渲染:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: node({ mode: 'standalone' }),
});• 每次请求动态生成页面
• 需要适配器(Node.js / Cloudflare / Vercel / Netlify)
• 适合:用户仪表盘、需要 session 的页面
3. Hybrid(混合)— 按页选择:
export default defineConfig({ output: 'static' }); // 默认静态
// 单个页面设为 SSR
// src/pages/admin.astro
export const prerender = false;或全局
output: 'server',单页 prerender = true适配器:
•
@astrojs/node — Node.js 服务器•
@astrojs/cloudflare — Cloudflare Workers•
@astrojs/vercel / @astrojs/netlify — 对应平台•
@astrojs/deno — Deno Deploy 查看答案即标记为已答
Integrations:Astro 的插件机制,扩展框架功能(框架支持、工具链、部署适配)。
1. 框架集成(UI Frameworks):
同一页面可混用多个框架的组件。
2. 工具集成:
3. 适配器集成:
配置方式:
官方 50+ 集成,社区更多。也可自定义 Integration。
1. 框架集成(UI Frameworks):
npx astro add react // 支持 React 组件
npx astro add vue // 支持 Vue 组件
npx astro add svelte // 支持 Svelte 组件
npx astro add solid // 支持 Solid 组件同一页面可混用多个框架的组件。
2. 工具集成:
npx astro add tailwind // Tailwind CSS
npx astro add mdx // MDX 支持
npx astro add sitemap // 站点地图
npx astro add partytown // 第三方脚本 Web Worker3. 适配器集成:
npx astro add cloudflare // 部署到 Cloudflare
npx astro add vercel // 部署到 Vercel配置方式:
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import tailwind from '@astrojs/tailwind';
export default defineConfig({
integrations: [react(), tailwind()],
});官方 50+ 集成,社区更多。也可自定义 Integration。
查看答案即标记为已答
1. 静态数据获取(构建时)— 默认方式:
在构建时执行一次,结果写入静态 HTML。
2. 动态数据获取(请求时)— SSR 模式:
3. Astro.server 路由(API Routes):
4. 客户端获取(运行时):
5. Content Collections(内容数据):
基于文件系统,Zod 验证,类型安全。
总结:静态页面用方式 1/5;动态页面用方式 2/3;客户端交互用方式 4。
---
// Frontmatter 中直接 await,构建时执行
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
---
<ul>
{posts.map(p => <li>{p.title}</li>)}
</ul>在构建时执行一次,结果写入静态 HTML。
2. 动态数据获取(请求时)— SSR 模式:
---
export const prerender = false; // 启用 SSR
const data = await fetch(request.url).then(r => r.json());
---3. Astro.server 路由(API Routes):
// src/pages/api/hello.ts
export async function GET({ params, request }) {
const data = await db.query('...');
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' },
});
}4. 客户端获取(运行时):
<script>
const data = await fetch('/api/hello').then(r => r.json());
</script>5. Content Collections(内容数据):
const posts = await getCollection('blog');基于文件系统,Zod 验证,类型安全。
总结:静态页面用方式 1/5;动态页面用方式 2/3;客户端交互用方式 4。
查看答案即标记为已答
| Astro | Next.js (SSG) | Gatsby | |
|---|---|---|---|
| 默认 JS 体积 | 0 KB | ~80KB+ (React) | ~100KB+ (React) |
| 框架绑定 | 无关(可用 React/Vue/Svelte) | React | React |
| 水合策略 | 岛屿架构(按需) | 整页水合 | 整页水合 |
| 内容处理 | Content Collections | 自行管理 | GraphQL 数据层 |
| 构建速度 | 快(Vite) | 快(Turbopack) | 慢(Webpack + GraphQL) |
| 页面切换 | View Transitions(原生) | SPA 路由 | SPA 路由 |
| 学习曲线 | 低 | 中 | 高(GraphQL) |
Astro 的核心优势:
1. 零 JS 默认:输出纯 HTML,不像 Gatsby/Next.js 即使静态页面也要加载 React 运行时。
2. 岛屿架构:只有交互部分加载 JS,非交互部分完全静态。Next.js/Gatsby 整页水合。
3. 框架无关:一个项目可以混用 React、Vue、Svelte 组件,迁移成本低。
4. 内容优先:Content Collections + Markdown/MDX 原生支持,适合内容型网站。
什么时候不用 Astro:
• 高度交互的 SPA(后台管理、社交应用)
• 需要 React Server Components
• 大量客户端状态管理
查看答案即标记为已答
Server Actions:在服务端执行的函数,可直接从客户端组件调用,无需手写 API 路由。
定义:
在 Client Component 中使用:
useActionState(状态管理):
优点:
• 无需编写 API 路由
• 渐进增强(即使 JS 禁用也能工作)
• 类型安全(端到端类型推导)
• 自动防 CSRF
定义:
// Server Component 中直接定义
async function createPost(formData: FormData) {
'use server';
const title = formData.get('title');
await db.post.create({ data: { title } });
revalidatePath('/posts');
}在 Client Component 中使用:
'use client';
// 从 Server Component 传入
<form action={serverAction}>
<input name="title" />
<button type="submit">提交</button>
</form>useActionState(状态管理):
const [state, formAction, isPending] = useActionState(serverAction, initialState);优点:
• 无需编写 API 路由
• 渐进增强(即使 JS 禁用也能工作)
• 类型安全(端到端类型推导)
• 自动防 CSRF
查看答案即标记为已答