ข้ามไปยังเนื้อหา

Dynamic Routes

ใน Next.js App Router คุณใช้ [slug]/page.tsx + generateStaticParams() เพื่อ pre-render หน้าแบบ dynamic ณ build time Astro ใช้ convention ชื่อไฟล์แบบ bracket เดียวกัน — [slug].astro — คู่กับ getStaticPaths() export ที่ จำเป็น ภายใน frontmatter

Dynamic route ต้องการการสร้างหลายหน้า — รัน example เหล่านี้ใน Astro project เต็มรูปแบบ (npm create astro@latest) ในเครื่องของคุณ

Next.js
// app/blog/[slug]/page.tsx (Next.js App Router)
export async function generateStaticParams() {
const posts = await getPosts();
return posts.map((post) => ({ slug: post.slug }));
}
export default function BlogPost({
params,
}: {
params: { slug: string };
}) {
return <h1>Post: {params.slug}</h1>;
}
Astro
---
// src/pages/blog/[slug].astro
export async function getStaticPaths() {
const posts = await getPosts();
return posts.map((post) => ({
params: { slug: post.slug },
props: { post }, // ส่งข้อมูลพร้อม params
}));
}
const { slug } = Astro.params;
const { post } = Astro.props;
---
<h1>{post.title}</h1>

สิ่งสำคัญที่ควรสังเกต:

  1. getStaticPaths() ถูก export จากภายใน frontmatter — ไม่ใช่เป็น separate file export แบบ Next.js
  2. แต่ละ path object มี field props เพื่อนำข้อมูลที่ fetch มาไว้คู่กับ path — ไม่ต้อง fetch ซ้ำในหน้า
  3. Astro.params เก็บค่า dynamic segment เทียบเท่ากับ params.slug ใน Next.js
Next.js Pages Router
// Next.js Pages Router equivalent
// pages/blog/[slug].tsx
import type { GetStaticPaths, GetStaticProps } from 'next';
export const getStaticPaths: GetStaticPaths = async () => {
const posts = await getPosts();
return {
paths: posts.map((p) => ({ params: { slug: p.slug } })),
fallback: false,
};
};
export const getStaticProps: GetStaticProps = async ({ params }) => {
const post = await getPost(params!.slug as string);
return { props: { post } };
};
export default function BlogPost({ post }: { post: Post }) {
return <article><h1>{post.title}</h1></article>;
}
Astro
---
// src/pages/blog/[slug].astro
// getStaticPaths + data fetching ในฟังก์ชันเดียว:
export async function getStaticPaths() {
const posts = await getPosts();
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
// props มาทาง Astro.props เหมือน component ทั่วไป
const { post } = Astro.props;
---
<article>
<h1>{post.title}</h1>
<div set:html={post.body} />
</article>
flowchart TD
  pages["src/pages/"] --> blog["blog/"]
  blog --> index["index.astro"]
  blog --> slug["[slug].astro"]
  index --> indexURL["/blog (list all posts)"]
  slug --> slugURL["/blog/:slug (individual post)"]
Blog file tree mapping files to routes

Astro รองรับ catch-all route แบบ rest-parameter ด้วย [...path].astro ซึ่งแมปกับ [[...slug]]/page.tsx ใน Next.js

Next.js
// app/docs/[[...slug]]/page.tsx
export default function DocsPage({
params,
}: {
params: { slug?: string[] };
}) {
const path = params.slug?.join('/') ?? '';
return <div>Docs path: {path}</div>;
}
Astro
---
// src/pages/docs/[...path].astro
const { path } = Astro.params;
// path เป็น string เช่น "getting-started/intro"
---
<div>Docs path: {path}</div>
ต้อง export ฟังก์ชันใดจากหน้า .astro แบบ dynamic เพื่อบอก Astro ว่าจะ pre-render path ใดบ้าง?
`getStaticPaths()` ถูกประกาศไว้ที่ใดในไฟล์ Astro dynamic route?
จะเข้าถึงค่า dynamic segment (เช่น slug) ภายในหน้า Astro ได้อย่างไร?
Astro เทียบเท่ากับ `[[...slug]]` catch-all segment ของ Next.js ด้วยอะไร?