⏱️4 min read · 851 words
SvelteKit هو إطار عمل الويب المتكامل الأسرع نموًا في عام 2026. تم تصميمه على Svelte 5 مع الأحرف الرونية (نظام بدائي تفاعلي جديد)، وعرض SvelteKit من جانب الخادم، ونشر الحافة، وفلسفة صفر JS افتراضيًا، مما يجعله بديلاً مقنعًا لـ Next.js للعديد من المشاريع. يغطي هذا الدليل كل شيء بدءًا من المكون الأول وحتى نشر الإنتاج.
📋 Table of Contents
ما الجديد في Svelte 5 وSvelteKit 2
- الرونية– الأوليات التفاعلية الجديدة: $state، $derived، $effect، $props
- مقتطفات– كتل ترميزية قابلة لإعادة الاستخدام بدون مكونات كاملة
- سمات الحدث —
onclickبدلاً منon:click - سفيلت كيت 2— توجيه سطحي، وتحسين التحميل المسبق، وتحسينات المحول
- أداء– يقوم Svelte بتجميع إطار العمل، ويشحن الحد الأدنى من JS
يثبت
npm create svelte@latest my-app
cd my-app
npm install
# Choose: SvelteKit, TypeScript, ESLint, Prettier, Playwright, Vitest
Svelte 5 مكونات مع الأحرف الرونية
<!-- Counter.svelte — Svelte 5 runes syntax -->
<script lang="ts">
// $state — reactive state (replaces let)
let count = $state(0);
let name = $state('World');
// $derived — computed values (replaces $: derived)
const doubled = $derived(count * 2);
const greeting = $derived(`Hello, ${name}! Count: ${count}`);
// $effect — side effects (replaces $: with side effects)
$effect(() => {
document.title = `Count: ${count}`;
return () => {
document.title = 'App'; // cleanup
};
});
function increment() {
count++;
}
</script>
<div class="counter">
<h2>{greeting}</h2>
<p>Doubled: {doubled}</p>
<!-- Svelte 5: onclick not on:click -->
<button onclick={increment}>+1</button>
<button onclick={() => count = 0}>Reset</button>
<input bind:value={name} placeholder="Your name" />
</div>
<style>
.counter {
padding: 1rem;
border: 1px solid var(--border);
border-radius: 8px;
}
</style>
الدعائم $ – الدعائم المكونة
<!-- Card.svelte -->
<script lang="ts">
interface Props {
title: string;
description?: string;
variant?: 'primary' | 'secondary';
onclick?: () => void;
children?: import('svelte').Snippet;
}
// $props replaces export let
const { title, description = '', variant = 'primary', onclick, children }: Props = $props();
</script>
<article class="card card--{variant}" onclick={onclick}>
<h3>{title}</h3>
{#if description}
<p>{description}</p>
{/if}
{#if children}
{@render children()}
{/if}
</article>
توجيه SvelteKit وتحميل البيانات
src/routes/
+page.svelte — home page
+layout.svelte — shared layout
+error.svelte — error page
blog/
+page.svelte — /blog
+page.server.ts — server-side load
[slug]/
+page.svelte — /blog/my-post
+page.server.ts
api/
users/
+server.ts — REST API routes
// src/routes/blog/+page.server.ts
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ fetch, url }) => {
const page = url.searchParams.get('page') ?? '1';
const response = await fetch(`/api/posts?page=${page}&limit=10`);
if (!response.ok) {
throw error(500, 'Failed to load posts');
}
const { posts, total } = await response.json();
return { posts, total, page: parseInt(page) };
};
<!-- src/routes/blog/+page.svelte -->
<script lang="ts">
import type { PageData } from './$types';
const { data } = $props<{ data: PageData }>();
const { posts, total, page } = $derived(data);
</script>
<svelte:head>
<title>Blog | TechPulse</title>
<meta name="description" content="Latest tech articles" />
</svelte:head>
<main>
<h1>Blog</h1>
{#each posts as post (post.id)}
<article>
<h2><a href="/blog/{post.slug}">{post.title}</a></h2>
<p>{post.excerpt}</p>
<time>{new Date(post.publishedAt).toLocaleDateString()}</time>
</article>
{/each}
<nav>
{#if page > 1}
<a href="?page={page - 1}">Previous</a>
{/if}
{#if posts.length === 10}
<a href="?page={page + 1}">Next</a>
{/if}
</nav>
</main>
طرق واجهة برمجة التطبيقات
// src/routes/api/users/+server.ts
import { json, error } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
export const GET: RequestHandler = async ({ url, locals }) => {
const page = parseInt(url.searchParams.get('page') ?? '1');
const limit = Math.min(parseInt(url.searchParams.get('limit') ?? '20'), 100);
const { users, total } = await locals.db.users.findMany({ page, limit });
return json({ users, total, page, limit });
};
export const POST: RequestHandler = async ({ request, locals }) => {
const body = await request.json();
// Validate with Zod
const result = createUserSchema.safeParse(body);
if (!result.success) {
throw error(422, { message: 'Validation failed', errors: result.error.errors });
}
const user = await locals.db.users.create(result.data);
return json(user, { status: 201 });
};
إجراءات النموذج
// src/routes/contact/+page.server.ts
import { fail, redirect } from '@sveltejs/kit';
import type { Actions } from './$types';
export const actions: Actions = {
default: async ({ request }) => {
const data = await request.formData();
const name = data.get('name') as string;
const email = data.get('email') as string;
const message = data.get('message') as string;
if (!name || !email || !message) {
return fail(422, { name, email, message, error: 'All fields required' });
}
await sendContactEmail({ name, email, message });
throw redirect(303, '/contact?success=true');
}
};
<!-- src/routes/contact/+page.svelte -->
<script lang="ts">
import { enhance } from '$app/forms';
const { form } = $props();
</script>
<form method="POST" use:enhance>
{#if form?.error}
<p class="error">{form.error}</p>
{/if}
<input name="name" value={form?.name ?? ''} required placeholder="Name" />
<input name="email" type="email" value={form?.email ?? ''} required placeholder="Email" />
<textarea name="message" required placeholder="Message">{form?.message ?? ''}</textarea>
<button type="submit">Send</button>
</form>
النشر
# Vercel (adapter-vercel)
npm install --save-dev @sveltejs/adapter-vercel
# Netlify (adapter-netlify)
npm install --save-dev @sveltejs/adapter-netlify
# Node.js server (adapter-node)
npm install --save-dev @sveltejs/adapter-node
# Cloudflare Workers (adapter-cloudflare)
npm install --save-dev @sveltejs/adapter-cloudflare
# svelte.config.js
import adapter from '@sveltejs/adapter-vercel';
export default { kit: { adapter: adapter() } };
يعد SvelteKit في عام 2026 ناضجًا وسريعًا وصديقًا للمطورين. يعد نظام الأحرف الرونية في Svelte 5 أكثر وضوحًا من التفاعل السحري في Svelte 4. بالنسبة للمشاريع التي يكون فيها حجم الحزمة وأداء وقت التشغيل أكثر أهمية من حجم النظام البيئي، يعد SvelteKit خيارًا مقنعًا على Next.js.
🔗 Share this article
✍️ Leave a Comment