Load Functions
ทุกแอปที่จริงจังต้องดึงข้อมูลก่อน render หน้า React ecosystem แก้ปัญหานี้มาหลายแบบตลอดหลายปี: react-router loader, Next.js getServerSideProps, Next.js App Router server component SvelteKit รวมทุกแบบเป็น convention เดียวที่คาดเดาได้: ฟังก์ชัน load ที่ export จากไฟล์ข้าง page ของคุณ
รันตัวอย่างนี้ในโปรเจกต์ SvelteKit (
npx sv create)
react-router loader เทียบกับ SvelteKit +page.js load
หัวข้อที่มีชื่อว่า “react-router loader เทียบกับ SvelteKit +page.js load”react-router v6.4+ แนะนำฟังก์ชัน loader — async function ที่รันก่อน route จะ render load ของ +page.js ใน SvelteKit คือแนวคิดเดียวกัน แต่ไฟล์อยู่ข้าง page แทนที่จะฝังใน route config object
// react-router v6.4 — route configimport { createBrowserRouter } from 'react-router-dom';import { useLoaderData } from 'react-router-dom';
async function postLoader({ params }) { const res = await fetch('/api/posts/' + params.id); return res.json();}
function PostPage() { const post = useLoaderData(); return <h1>{post.title}</h1>;}
const router = createBrowserRouter([ { path: '/posts/:id', element: <PostPage />, loader: postLoader, },]);// src/routes/posts/[id]/+page.jsexport async function load({ params, fetch }) { const res = await fetch('/api/posts/' + params.id); const post = await res.json(); return { post };}load ของ +page.js รันทั้ง บน server (request แรก) และบน client (การนำทางของ SvelteKit) ซึ่งหมายความว่าคุณได้ server-rendered HTML ตอนโหลดครั้งแรก และการเปลี่ยนหน้าฝั่ง client ที่รวดเร็วในการนำทางครั้งต่อไป — ได้มาฟรี ๆ
รับ data ใน page component
หัวข้อที่มีชื่อว่า “รับ data ใน page component”สิ่งที่ load return จะเข้าถึงได้ในชื่อ data ผ่าน \$props():
<script> let { data } = $props(); // data.post is the object returned from load()</script>
<h1>{data.post.title}</h1><p>{data.post.body}</p>TypeScript: import PageLoad (สำหรับ +page.js) หรือ PageServerLoad (สำหรับ +page.server.js) จากไฟล์ ./$types ที่สร้างอัตโนมัติ:
// +page.js (universal)import type { PageLoad } from './$types';
export const load: PageLoad = async ({ params, fetch }) => { const post = await fetch('/api/posts/' + params.id).then(r => r.json()); return { post };};Next.js getServerSideProps เทียบกับ SvelteKit +page.server.js
หัวข้อที่มีชื่อว่า “Next.js getServerSideProps เทียบกับ SvelteKit +page.server.js”getServerSideProps คือ data loader ฝั่ง server เท่านั้นของ Next.js Pages Router — รันบน server อย่างเดียว เข้าถึงฐานข้อมูลและ secret ได้ แล้วส่งข้อมูลเป็น props ให้ page component +page.server.js ของ SvelteKit คือ equivalent โดยตรง
// Next.js Pages Router — pages/posts/[id].tsxexport async function getServerSideProps({ params }) { const post = await db.post.findUnique({ where: { id: Number(params.id) }, }); return { props: { post } };}
export default function PostPage({ post }) { return <h1>{post.title}</h1>;}// src/routes/posts/[id]/+page.server.jsimport { db } from '$lib/db';
export async function load({ params, cookies }) { const post = await db.post.findUnique({ where: { id: Number(params.id) }, }); return { post };}เวอร์ชัน +page.server.js:
- รัน บน server เท่านั้น — ปลอดภัยสำหรับ DB query, secret, private env var
- รับ
cookiesเพิ่มเติมจากparams,fetch, และurl - return plain object; SvelteKit serialise แล้วส่งให้ client เป็น
data
แจ้ง 404 ด้วย error()
หัวข้อที่มีชื่อว่า “แจ้ง 404 ด้วย error()”ทั้ง +page.js และ +page.server.js ควรแจ้งว่า resource หาไม่เจอด้วย helper error() จาก @sveltejs/kit แทนที่จะ throw plain object เอง — SvelteKit จะ render หน้า +error.svelte ที่ถูกต้องให้ ตั้งแต่ SvelteKit 2 เป็นต้นมา error() จะ throw ให้เองภายใน จึงเรียกโดยไม่ต้องมี throw นำหน้า:
import { db } from '$lib/db';import { error } from '@sveltejs/kit';
export async function load({ params }) { const post = await db.post.findUnique({ where: { slug: params.slug } }); if (!post) error(404, 'Not found'); return { post };}เลือก +page.js หรือ +page.server.js
หัวข้อที่มีชื่อว่า “เลือก +page.js หรือ +page.server.js”+page.js (universal) | +page.server.js (server-only) | |
|---|---|---|
| Runs on server | Yes (initial request) | Yes (always) |
| Runs on client | Yes (navigations) | No |
Access cookies | No | Yes |
| Access DB directly | Not recommended | Yes |
| Access private env vars | No | Yes |
fetch is available | Yes (enhanced) | Yes (enhanced) |
วิธีตัดสินใจแบบไว ตามสถานการณ์:
| สถานการณ์ | ไฟล์ที่ควรใช้ |
|---|---|
| เรียก public REST API | +page.js |
| ต้องการ fetch ทั้งบน server (SSR) และ client (navigation) | +page.js |
| Query ฐานข้อมูลโดยตรง | +page.server.js |
| อ่าน cookie หรือ session | +page.server.js |
| ใช้ API key ที่เป็น secret | +page.server.js |
หลักคิดง่าย ๆ: ถ้าไม่อยากให้โค้ดดังกล่าวปรากฏใน browser bundle ให้ใช้ +page.server.js
Argument ของฟังก์ชัน load
หัวข้อที่มีชื่อว่า “Argument ของฟังก์ชัน load”ทั้ง universal และ server load function รับ argument หลักชุดเดียวกัน:
// +page.js or +page.server.jsexport async function load({ params, fetch, url, cookies }) { // params — route parameters, e.g. params.slug // fetch — SvelteKit-enhanced fetch (sets cookies, handles relative URLs) // url — the current URL as a URL object // cookies — (server only) read/write cookies}