โครงสร้างโปรเจกต์
โปรเจกต์ Astro ที่เพิ่งสร้างใหม่จะดูคุ้นเคยถ้าคุณรู้จัก Next.js แต่หลาย convention มีความแตกต่างกันเล็กน้อย สิ่งสำคัญที่สุด: src/pages/ คือ directory เดียวที่ Astro ถือว่าพิเศษสำหรับ routing — ส่วนที่เหลือขึ้นอยู่กับคุณ
โครงสร้างแบบเทียบเคียง
หัวข้อที่มีชื่อว่า “โครงสร้างแบบเทียบเคียง”my-next-app/├── src/│ ├── app/ # App Router pages (Next 13+)│ │ ├── page.tsx # → /│ │ └── about/│ │ └── page.tsx # → /about│ ├── components/ # Shared React components│ └── lib/ # Utilities├── public/ # Static assets (served at /)├── next.config.mjs # Framework config└── package.jsonmy-astro-app/├── src/│ ├── pages/ # File-based routes (special)│ │ ├── index.astro # → /│ │ └── about.astro # → /about│ ├── components/ # .astro and framework components│ ├── layouts/ # Layout wrappers (Astro convention)│ └── content/ # Content Collections (MDX, YAML, JSON)├── public/ # Static assets (served at /)├── astro.config.mjs # Framework config└── package.jsonความแตกต่างสำคัญที่ควรสังเกต:
src/pages/— ไม่ใช่src/app/Astro ใช้ mental model แบบ Pages Router: ไฟล์ที่src/pages/about.astrorender ที่/aboutไม่ต้อง wrapperpage.tsxพิเศษsrc/layouts/เป็น convention ไม่ใช่กฎของ framework Astro ไม่บังคับให้มี directorylayouts/— แต่ทุกโปรเจกต์ Astro ก็ใช้ตาม convention เพราะ layout component เป็น pattern ที่สำคัญ (ครอบคลุมในโมดูล Layouts)src/content/ใช้สำหรับ Content Collections — เนื้อหาที่มีโครงสร้าง เช่น บทความ MDX, ไฟล์ YAML ของสมาชิกทีม หรือข้อมูล JSON Astro มี typed API สำหรับ query เนื้อหาเหล่านี้ คุณจะใช้getStaticPaths+getEntryแทนgetStaticProps+ การอ่านไฟล์astro.config.mjsแทนnext.config.mjsแนวคิดเดียวกัน — framework config, integration, Vite override
โฟลเดอร์ public/
หัวข้อที่มีชื่อว่า “โฟลเดอร์ public/”ทั้ง Next.js และ Astro มี directory public/ ไฟล์ที่วางไว้ที่นั่นจะถูก serve ที่ root URL ตามที่เป็น — ไม่มี bundle, ไม่มี transform ไฟล์ที่ public/logo.png จะเข้าถึงได้ที่ /logo.png
ความแตกต่าง: ใน Next.js คุณอ้างอิงรูปภาพด้วย component <Image> เพื่อ optimise ใน Astro คุณใช้ tag <img> ธรรมดา (หรือ image optimisation ที่มีใน Astro — import { Image } from 'astro:assets')
astro.config.mjs
หัวข้อที่มีชื่อว่า “astro.config.mjs”import { defineConfig } from 'astro/config';import react from '@astrojs/react';import tailwind from '@astrojs/tailwind';
export default defineConfig({ site: 'https://my-site.com', integrations: [react(), tailwind()], // Vite config lives inside vite: {}});เทียบกับ next.config.mjs — รูปแบบคล้ายกัน (default export ที่คืน config object) แต่ key ต่างกัน Astro ไม่มี experimental, rewrites, หรือ redirects เป็น top-level key สิ่งเหล่านั้นผ่าน Vite หรือ Astro middleware
หน้าที่รันได้แสดงโครงสร้าง
หัวข้อที่มีชื่อว่า “หน้าที่รันได้แสดงโครงสร้าง”---
// src/pages/index.astro
// Frontmatter: runs at build/server time
const siteName = "My Astro Site";
const navLinks = [
{ href: "/", label: "Home" },
{ href: "/about", label: "About" },
{ href: "/blog", label: "Blog" },
];
---
<html lang="en">
<head>
<meta charset="utf-8" />
<title>{siteName}</title>
<style>
body { font-family: sans-serif; margin: 0; }
nav { background: #1e1b4b; padding: 1rem 2rem; display: flex; gap: 1.5rem; }
nav a { color: #c7d2fe; text-decoration: none; font-size: 0.9rem; }
nav a:hover { color: #fff; }
main { padding: 2rem; }
.badge { background: #ede9fe; color: #4c1d95; padding: 0.2rem 0.6rem; border-radius: 4px; font-size: 0.75rem; }
</style>
</head>
<body>
<nav>
{navLinks.map(link => (
<a href={link.href}>{link.label}</a>
))}
</nav>
<main>
<span class="badge">src/pages/index.astro</span>
<h1>Welcome to {siteName}</h1>
<p>This page lives at <code>src/pages/index.astro</code> and renders at <code>/</code>.</p>
<p>Components go in <code>src/components/</code>, layouts in <code>src/layouts/</code>.</p>
</main>
</body>
</html>