9.9 דיפלוימנט וארכיטקטורה הרצאה
דיפלוימנט וארכיטקטורה - Deployment and Architecture¶
בשיעור זה נלמד איך לבנות ולפרוס אפליקציית Next.js לייצור, איך לנהל משתני סביבה, ואיך לתכנן ארכיטקטורה נכונה לפרויקט.
בנייה לייצור - Building for Production¶
פקודת build¶
הפקודה מבצעת:
- קומפילציה של TypeScript
- אופטימיזציות: minification, tree shaking, code splitting
- יצירת דפים סטטיים (SSG)
- Pre-rendering של Server Components
- ייצור manifest של כל הנתיבים
פלט לדוגמה:
Route (app) Size First Load JS
/ 5.2 kB 90.3 kB
/about 1.2 kB 86.3 kB
/blog 2.8 kB 88.0 kB
/blog/[slug] 3.1 kB 88.2 kB
/api/posts 0 B 0 B
/dashboard 4.5 kB 89.6 kB
First Load JS shared by all 85.1 kB
chunks/main-abc123.js 60.2 kB
chunks/pages-def456.js 24.9 kB
Symbols:
○ Static
λ Dynamic (server-rendered)
ƒ Dynamic (uses fetch)
○סטטי - נבנה בזמן buildλדינמי - נבנה בכל בקשהƒדינמי עם fetch
הרצה בייצור¶
- מריץ את הגרסה שנבנתה
- אין hot reload או developer tools
- ביצועים מיטביים
דיפלוי לוורסל - Deploying to Vercel¶
Vercel היא הפלטפורמה המומלצת לפריסת Next.js (אותה חברה שפיתחה את נקסט).
דיפלוי מ-Git¶
- העלו את הפרויקט ל-GitHub
- היכנסו ל-vercel.com והתחברו עם GitHub
- בחרו את ה-repository
- Vercel מזהה אוטומטית שזה פרויקט Next.js
- לחצו Deploy
הגדרות בוורסל¶
- Build Command:
npm run build(אוטומטי) - Output Directory:
.next(אוטומטי) - Install Command:
npm install(אוטומטי) - משתני סביבה: מוגדרים בהגדרות הפרויקט
דיפלוי אוטומטי¶
- כל push ל-main מפעיל דיפלוי לייצור
- כל push לענף אחר מייצר Preview deployment
- אפשר לחבר ל-PR של GitHub לקבלת preview URL
משתני סביבה - Environment Variables¶
סוגי משתנים¶
# .env.local - משתני סביבה מקומיים (לא עולה ל-git)
DATABASE_URL="file:./dev.db"
AUTH_SECRET="my-secret"
API_KEY="secret-api-key"
# משתנים שזמינים בדפדפן - חייבים להתחיל ב-NEXT_PUBLIC_
NEXT_PUBLIC_API_URL="https://api.example.com"
NEXT_PUBLIC_SITE_URL="https://mysite.com"
- משתנים רגילים זמינים רק בשרת (Server Components, Server Actions, Route Handlers)
- משתנים עם
NEXT_PUBLIC_זמינים גם בדפדפן - לא לשים בהם סודות
קבצי סביבה¶
.env # ברירת מחדל לכל הסביבות
.env.local # מקומי - דורס את .env
.env.development # רק במצב development
.env.production # רק במצב production
- סדר עדיפות:
.env.local>.env.development/.env.production>.env .env.localלא עולה ל-git (כבר ב-.gitignore של Next.js)
שימוש בקוד¶
// Server Component - גישה למשתנים רגילים
export default function Page() {
const dbUrl = process.env.DATABASE_URL;
const apiKey = process.env.API_KEY;
return <div>מחובר לבסיס נתונים</div>;
}
// Client Component - רק NEXT_PUBLIC_
"use client";
export default function ApiInfo() {
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
return <p>כתובת API: {apiUrl}</p>;
}
ארכיטקטורת פרויקט - Project Architecture¶
מבנה תיקיות מומלץ¶
app/
(auth)/ # Route Group - דפי אותנטיקציה
login/
page.tsx
register/
page.tsx
layout.tsx
(main)/ # Route Group - אפליקציה ראשית
layout.tsx
page.tsx
dashboard/
page.tsx
settings/
page.tsx
api/
posts/
route.ts
users/
route.ts
components/ # קומפוננטות משותפות
ui/ # קומפוננטות UI בסיסיות
Button.tsx
Input.tsx
Card.tsx
Modal.tsx
layout/ # קומפוננטות מבנה
Navbar.tsx
Footer.tsx
Sidebar.tsx
forms/ # קומפוננטות טפסים
LoginForm.tsx
PostForm.tsx
actions/ # Server Actions
auth.ts
posts.ts
users.ts
hooks/ # Custom hooks
useDebounce.ts
useLocalStorage.ts
lib/ # ספריות ועזרים
prisma.ts
utils.ts
constants.ts
validations.ts
types/ # טיפוסי TypeScript
index.ts
post.ts
user.ts
prisma/
schema.prisma
migrations/
seed.ts
public/
images/
fonts/
עקרונות ארכון¶
- הפרדת אחריות: כל קובץ עושה דבר אחד
- קומפוננטות קטנות: קומפוננטה לא צריכה להיות ארוכה מדי
- שימוש חוזר: קוד שמשתמשים בו יותר מפעם אחת - לתיקייה משותפת
- Colocation: קבצים קשורים יושבים קרוב זה לזה
תבנית Feature-Based¶
לפרויקטים גדולים, מומלץ לארגן לפי פיצ'רים:
app/
(features)/
posts/
components/
PostCard.tsx
PostForm.tsx
PostList.tsx
actions.ts
types.ts
page.tsx
[id]/
page.tsx
users/
components/
UserCard.tsx
UserList.tsx
actions.ts
types.ts
page.tsx
comments/
components/
CommentForm.tsx
CommentList.tsx
actions.ts
components/ # קומפוננטות גלובליות
lib/ # ספריות משותפות
- כל פיצ'ר מכיל את הקומפוננטות, ה-actions, והטיפוסים שלו
- קל להבין מה שייך למה
- קל להוסיף או להסיר פיצ'רים
טיפול בשגיאות - Error Handling¶
שגיאות ברמת הדף¶
// app/error.tsx
"use client";
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<div className="min-h-[50vh] flex flex-col items-center justify-center">
<h2 className="text-2xl font-bold mb-4">משהו השתבש</h2>
<p className="text-gray-600 mb-4">{error.message}</p>
<button
onClick={reset}
className="px-4 py-2 bg-blue-500 text-white rounded"
>
נסה שוב
</button>
</div>
);
}
שגיאות ב-Server Actions¶
"use server";
interface ActionResult<T = void> {
success: boolean;
data?: T;
error?: string;
}
export async function createPost(
formData: FormData
): Promise<ActionResult<{ id: number }>> {
try {
// ולידציה
const title = formData.get("title") as string;
if (!title) {
return { success: false, error: "כותרת היא שדה חובה" };
}
// יצירה
const post = await prisma.post.create({
data: { title, content: "", slug: "", authorId: 1 },
});
revalidatePath("/posts");
return { success: true, data: { id: post.id } };
} catch (error) {
console.error("Error creating post:", error);
return { success: false, error: "שגיאה ביצירת הפוסט" };
}
}
שגיאות גלובליות¶
// app/global-error.tsx
"use client";
export default function GlobalError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<html>
<body>
<div className="min-h-screen flex items-center justify-center">
<div className="text-center">
<h2 className="text-3xl font-bold mb-4">שגיאה קריטית</h2>
<button
onClick={reset}
className="px-6 py-3 bg-blue-500 text-white rounded"
>
נסה שוב
</button>
</div>
</div>
</body>
</html>
);
}
ספריית עזר - Utility Library¶
// lib/utils.ts
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
// מיזוג className עם Tailwind
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
// פורמט תאריך
export function formatDate(date: Date | string): string {
return new Date(date).toLocaleDateString("he-IL", {
year: "numeric",
month: "long",
day: "numeric",
});
}
// השהייה (לפיתוח)
export function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// יצירת slug מכותרת
export function slugify(text: string): string {
return text
.toLowerCase()
.replace(/\s+/g, "-")
.replace(/[^a-z0-9-]/g, "")
.replace(/-+/g, "-")
.trim();
}
// lib/validations.ts
export function validateEmail(email: string): boolean {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(email);
}
export function validatePassword(password: string): string | null {
if (password.length < 6) return "הסיסמה חייבת להכיל לפחות 6 תווים";
if (!/[A-Z]/.test(password)) return "הסיסמה חייבת להכיל אות גדולה";
if (!/[0-9]/.test(password)) return "הסיסמה חייבת להכיל ספרה";
return null;
}
מוניטורינג ואנליטיקס - Monitoring and Analytics¶
לוגינג¶
// lib/logger.ts
export function log(level: "info" | "warn" | "error", message: string, data?: any) {
const timestamp = new Date().toISOString();
if (level === "error") {
console.error(`[${timestamp}] ERROR: ${message}`, data);
} else if (level === "warn") {
console.warn(`[${timestamp}] WARN: ${message}`, data);
} else {
console.log(`[${timestamp}] INFO: ${message}`, data);
}
}
אנליטיקס עם Vercel Analytics¶
// app/layout.tsx
import { Analytics } from "@vercel/analytics/react";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="he" dir="rtl">
<body>
{children}
<Analytics />
</body>
</html>
);
}
ביצועים עם Vercel Speed Insights¶
// app/layout.tsx
import { SpeedInsights } from "@vercel/speed-insights/next";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="he" dir="rtl">
<body>
{children}
<SpeedInsights />
</body>
</html>
);
}
רשימת בדיקות לפני דיפלוי¶
- כל משתני הסביבה הוגדרו בפלטפורמת הדיפלוי
- הרצת
npm run buildעוברת בהצלחה ללא שגיאות - הרצת
npm run lintללא שגיאות - בדיקת ביצועים עם Lighthouse (ציון מעל 90)
- בדיקת מטא-דאטה ו-SEO
- בדיקת תמונות ופונטים (אופטימיזציה)
- בדיקת טפסים ו-Server Actions
- בדיקת אותנטיקציה והרשאות
- בדיקת responsive design
- הגדרת דומיין מותאם אישית (אם רלוונטי)
סיכום¶
npm run buildבונה את האפליקציה לייצור עם אופטימיזציות- Vercel היא הפלטפורמה המומלצת לדיפלוי Next.js
- משתני סביבה: רגילים לשרת,
NEXT_PUBLIC_לקליינט - ארכיטקטורה טובה מחלקת קוד לפי אחריות או פיצ'רים
- טיפול בשגיאות ברמות שונות: דף, action, גלובלי
- מוניטורינג ואנליטיקס חשובים למעקב אחרי ביצועים
- רשימת בדיקות לפני כל דיפלוי מבטיחה איכות