File-based Routing
ใน react-router คุณประกาศ route ด้วย JavaScript ใน Next.js คุณสร้างไฟล์ในโฟลเดอร์ pages/ หรือ app/ SvelteKit ทำงานเหมือน Next.js App Router: สร้างโฟลเดอร์ เพิ่ม +page.svelte แล้วคุณก็ได้ route แล้ว ไม่ต้อง import ไม่ต้องตั้งค่า route ไม่ต้องมี wrapping component
รันตัวอย่างนี้ในโปรเจกต์ SvelteKit (
npx sv create)
Basic routes
หัวข้อที่มีชื่อว่า “Basic routes”กรณีง่ายที่สุด: static path map ตรงไปยังโฟลเดอร์ + +page.svelte
// react-router v6import { createBrowserRouter } from 'react-router-dom';import About from './pages/About';
const router = createBrowserRouter([ { path: '/about', element: <About /> },]);<!-- src/routes/about/+page.svelte --><!-- This file IS the /about route. No config needed. -->
<h1>About</h1><p>Welcome to the about page.</p>Dynamic routes: [param]
หัวข้อที่มีชื่อว่า “Dynamic routes: [param]”react-router ใช้ :id ใน path string Next.js ใช้ [id] ในชื่อไฟล์ SvelteKit ใช้ [param] เป็น ชื่อโฟลเดอร์ — ชื่อโฟลเดอร์ (ไม่รวมวงเล็บ) จะกลายเป็น key ของ parameter
// react-router v6{ path: '/posts/:id', element: <PostPage /> }
// Next.js Pages Router// pages/posts/[id].tsx
// Next.js App Router// app/posts/[id]/page.tsx<!-- src/routes/posts/[id]/+page.svelte --><!-- Matches /posts/1, /posts/hello, /posts/anything -->
<h1>Post detail page</h1>Route file-tree walkthrough
หัวข้อที่มีชื่อว่า “Route file-tree walkthrough”โครงสร้าง src/routes/ ของ SvelteKit ในสถานการณ์จริง:
flowchart TB routes(["src/routes/"]) routes --> rootPage["+page.svelte → /"] routes --> about["about/"] about --> aboutPage["+page.svelte → /about"] routes --> blog["blog/"] blog --> blogPage["+page.svelte → /blog"] blog --> slug["[slug]/"] slug --> slugPage["+page.svelte → /blog/:slug"] routes --> dashboard["dashboard/"] dashboard --> dashLayout["+layout.svelte (shared layout)"] dashboard --> dashPage["+page.svelte → /dashboard"] dashboard --> settings["settings/"] settings --> settingsPage["+page.svelte → /dashboard/settings"]
ทุก +page.svelte คือ route หนึ่งเส้น +layout.svelte ภายใน dashboard/ ครอบทุกหน้าในโฟลเดอร์นั้นและโฟลเดอร์ลูก — เทียบเท่ากับ layout route ที่ใช้ <Outlet> ใน react-router หรือ layout.tsx ใน Next.js App Router
Nested layouts
หัวข้อที่มีชื่อว่า “Nested layouts”+layout.svelte ใน level ใดก็ตามจะครอบทุก route ในโฟลเดอร์นั้นและโฟลเดอร์ลูก — ตรงกับ layout.tsx ของ Next.js App Router หรือ layout route ที่ใช้ <Outlet> ของ react-router:
// react-router v6 — nested layout{ path: '/dashboard', element: <DashboardLayout />, children: [ { index: true, element: <DashboardHome /> }, { path: 'settings', element: <Settings /> }, ]}
// DashboardLayout.jsximport { Outlet } from 'react-router-dom';function DashboardLayout() { return ( <div> <nav>Dashboard nav</nav> <Outlet /> </div> );}<!-- src/routes/dashboard/+layout.svelte --><script> let { children } = $props();</script>
<nav>Dashboard nav</nav>{@render children()}
<!-- src/routes/dashboard/+page.svelte --><h1>Dashboard Home</h1>
<!-- src/routes/dashboard/settings/+page.svelte --><h1>Settings</h1>{@render children()} ใน +layout.svelte คือจุดที่ child page จะถูก render เข้าไป — ทำหน้าที่เหมือน <Outlet /> ของ react-router พอดี ทุก level ของโฟลเดอร์สามารถมี +layout.svelte ของตัวเอง — layouts ซ้อนกันได้ไม่จำกัด
Accessing route params
หัวข้อที่มีชื่อว่า “Accessing route params”ผ่านฟังก์ชัน load (แนะนำ)
หัวข้อที่มีชื่อว่า “ผ่านฟังก์ชัน load (แนะนำ)”วิธีที่ clean ที่สุดคืออ่าน params ใน +page.js หรือ +page.server.js แล้วส่งให้ component ผ่าน data component ไม่ต้องรู้เรื่อง param เลย
export async function load({ params }) { const post = await fetchPost(params.slug); return { post };}<script> let { data } = $props(); // data.post is what load() returned</script>
<h1>{data.post.title}</h1><article>{@html data.post.content}</article>ผ่าน $page store (เข้าถึงโดยตรง)
หัวข้อที่มีชื่อว่า “ผ่าน $page store (เข้าถึงโดยตรง)”คุณสามารถอ่าน params โดยตรงใน component ผ่าน $page store จาก $app/state:
<script> import { page } from '$app/state'; // page.params.slug is the current [slug] value</script>
<p>Viewing slug: {page.params.slug}</p>แนวทาง load function เป็นวิธีที่แนะนำ — มันเก็บ data fetching ไว้ด้วยกันและมี type ให้ และทำงานได้ดีกับ server-side rendering