9.1 הקדמה לנקסט הרצאה
הקדמה לנקסט - Next.js Introduction¶
בשיעור זה נכיר את Next.js - הפריימוורק המוביל לפיתוח אפליקציות ווב מלאות מבוססות React. נבין למה הוא קיים, מה היתרונות שלו על פני React רגיל, ונלמד ליצור פרויקט ראשון.
מה זה נקסט - Next.js?¶
- נקסט הוא פריימוורק מבוסס React שפותח על ידי חברת Vercel
- הוא מוסיף על React יכולות שלא קיימות בו כברירת מחדל: ראוטינג, רינדור בצד השרת, אופטימיזציות ועוד
- נקסט הוא פריימוורק full-stack - הוא מאפשר לכתוב גם קוד שרת וגם קוד קליינט בפרויקט אחד
למה לא להשתמש ב-React רגיל?¶
- ריאקט לבדו הוא ספרייה לבניית ממשק משתמש - לא פריימוורק שלם
- בפרויקט React רגיל (כמו עם Vite) צריך להוסיף בעצמנו ראוטינג, ניהול מטא-דאטה, אופטימיזציות ועוד
- כל הרינדור קורה בצד הלקוח (CSR) מה שפוגע ב-SEO ובביצועים
- נקסט פותר את כל הבעיות האלה ונותן פתרון מובנה ומוכן
אסטרטגיות רינדור - Rendering Strategies¶
אחד הנושאים החשובים ביותר בנקסט הוא הבנת דרכי הרינדור השונות.
רינדור בצד הלקוח - CSR (Client-Side Rendering)¶
- זה מה שקורה ב-React רגיל
- הדפדפן מקבל קובץ HTML ריק ואת קוד ה-JavaScript
- הדפדפן מריץ את ה-JS ובונה את ה-DOM
- החיסרון: המשתמש רואה מסך ריק עד שה-JS נטען ורץ
// כך עובד CSR - הדפדפן מקבל HTML כמעט ריק
// <div id="root"></div>
// ואז React בונה את כל התוכן ב-JS
function App() {
const [data, setData] = useState(null);
useEffect(() => {
fetch("/api/data").then(res => res.json()).then(setData);
}, []);
if (!data) return <div>Loading...</div>;
return <div>{data.title}</div>;
}
רינדור בצד השרת - SSR (Server-Side Rendering)¶
- השרת מריץ את הקוד ויוצר HTML מלא
- הדפדפן מקבל HTML מוכן עם כל התוכן
- המשתמש רואה תוכן מיד, עוד לפני שה-JS נטען
- בנקסט, SSR קורה בכל בקשה (request)
יצירת דפים סטטיים - SSG (Static Site Generation)¶
- הדפים נבנים בזמן ה-build, לא בזמן הבקשה
- מתאים לתוכן שלא משתנה לעתים קרובות (בלוג, תיעוד)
- הכי מהיר - הדפים כבר מוכנים ומוגשים מ-CDN
- בנקסט עם App Router, זו ברירת המחדל לדפים ללא נתונים דינמיים
רגנרציה סטטית מצטברת - ISR (Incremental Static Regeneration)¶
- שילוב של SSG ו-SSR
- הדף נבנה סטטית, אבל מתעדכן מחדש אחרי זמן מוגדר
- מתאים לתוכן שמשתנה אבל לא בזמן אמת
// דוגמה ל-ISR - הדף מתעדכן כל 60 שניות
async function Page() {
const res = await fetch("https://api.example.com/posts", {
next: { revalidate: 60 },
});
const posts = await res.json();
return (
<div>
{posts.map((post: any) => (
<h2 key={post.id}>{post.title}</h2>
))}
</div>
);
}
השוואה בין האסטרטגיות¶
| אסטרטגיה | זמן רינדור | מתאים ל | SEO |
|---|---|---|---|
| CSR | בדפדפן | אפליקציות דינמיות, דשבורדים | חלש |
| SSR | בכל בקשה | תוכן מותאם אישית | מצוין |
| SSG | בזמן build | תוכן סטטי, בלוגים | מצוין |
| ISR | בזמן build + עדכון | תוכן שמשתנה לפעמים | מצוין |
יצירת פרויקט נקסט - Next.js¶
ניצור פרויקט חדש באמצעות הכלי הרשמי של נקסט:
בזמן ההתקנה נקבל שאלות:
Would you like to use TypeScript? Yes
Would you like to use ESLint? Yes
Would you like to use Tailwind CSS? Yes
Would you like your code inside a `src/` directory? No
Would you like to use App Router? (recommended) Yes
Would you like to use Turbopack for next dev? Yes
Would you like to customize the import alias? No
- תמיד נבחר App Router (ולא Pages Router הישן)
- נבחר TypeScript כי זה הסטנדרט
- Tailwind CSS נבחר לפי העדפה
התקנה והרצה¶
- שרת הפיתוח ירוץ על
http://localhost:3000 - כל שינוי בקוד יתעדכן אוטומטית (Hot Reload)
מבנה הפרויקט - Project Structure¶
my-app/
app/
layout.tsx # לייאאוט ראשי - עוטף את כל הדפים
page.tsx # דף הבית (/)
globals.css # סגנונות גלובליים
favicon.ico # אייקון האתר
public/ # קבצים סטטיים (תמונות, פונטים)
next.config.ts # הגדרות נקסט
tsconfig.json # הגדרות TypeScript
tailwind.config.ts # הגדרות Tailwind
package.json # תלויות ופקודות
.env.local # משתני סביבה (לא עולה ל-git)
תיקיית app¶
- זו התיקייה המרכזית - כאן חי כל הקוד של האפליקציה
- כל קובץ
page.tsxמייצג דף (route) - כל קובץ
layout.tsxמגדיר מסגרת לדפים
תיקיית public¶
- קבצים סטטיים שזמינים ישירות מהשורש
- לדוגמה:
public/logo.pngזמין ב-/logo.png
קובץ הגדרות - next.config.ts¶
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
// הגדרות נקסט כאן
images: {
remotePatterns: [
{
protocol: "https",
hostname: "example.com",
},
],
},
};
export default nextConfig;
קבצי הליבה - Core Files¶
לייאאוט ראשי - Root Layout¶
קובץ app/layout.tsx הוא הלייאאוט הראשי. הוא חובה ועוטף את כל הדפים:
// app/layout.tsx
import type { Metadata } from "next";
import "./globals.css";
export const metadata: Metadata = {
title: "My App",
description: "My first Next.js app",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="he" dir="rtl">
<body>{children}</body>
</html>
);
}
- הלייאאוט הראשי חייב להכיל תגיות
<html>ו-<body> - הוא מקבל
children- זה התוכן של הדף הנוכחי - כאן מגדירים את שפת האתר, כיוון הטקסט, ומטא-דאטה
דף הבית - Home Page¶
קובץ app/page.tsx הוא דף הבית:
// app/page.tsx
export default function HomePage() {
return (
<main>
<h1>ברוכים הבאים</h1>
<p>זהו דף הבית של האפליקציה</p>
</main>
);
}
- כל קובץ
page.tsxמייצא קומפוננטה כ-default export - הנתיב (route) נקבע לפי המיקום בתיקיית
app
פקודות פיתוח - Development Commands¶
הרצת שרת פיתוח¶
- מריץ את האפליקציה במצב פיתוח על פורט 3000
- כולל Hot Module Replacement - שינויים מתעדכנים מיד
- הודעות שגיאה מפורטות
בנייה לייצור - Build¶
- בונה את האפליקציה לייצור
- מבצע אופטימיזציות: minification, code splitting, tree shaking
- יוצר דפים סטטיים כשאפשר
- מציג סיכום של כל הדפים והגודל שלהם
Route (app) Size First Load JS
/ 5.2 kB 85.3 kB
/about 1.2 kB 81.3 kB
/blog/[slug] 3.1 kB 83.2 kB
First Load JS shared by all 80.1 kB
הרצה בייצור¶
- מריץ את הגרסה הבנויה (אחרי build)
- כך זה ירוץ בשרת הייצור
לינט - Lint¶
- בודק שגיאות ותקינות קוד עם ESLint
- נקסט מגיע עם כללי ESLint מובנים
דוגמה מלאה - פרויקט ראשון¶
ניצור אפליקציה פשוטה עם דף בית ודף אודות:
שלב 1 - יצירת הפרויקט¶
שלב 2 - עדכון הלייאאוט הראשי¶
// app/layout.tsx
import type { Metadata } from "next";
import "./globals.css";
export const metadata: Metadata = {
title: "האפליקציה הראשונה שלי",
description: "לומדים Next.js",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="he" dir="rtl">
<body>
<nav style={{ padding: "1rem", borderBottom: "1px solid #ccc" }}>
<a href="/" style={{ marginLeft: "1rem" }}>בית</a>
<a href="/about">אודות</a>
</nav>
{children}
</body>
</html>
);
}
שלב 3 - עדכון דף הבית¶
// app/page.tsx
export default function HomePage() {
return (
<main style={{ padding: "2rem" }}>
<h1>ברוכים הבאים לאפליקציה</h1>
<p>זוהי אפליקציית Next.js ראשונה עם App Router</p>
<section style={{ marginTop: "2rem" }}>
<h2>מה נלמד?</h2>
<ul>
<li>ראוטינג מבוסס קבצים</li>
<li>רינדור בצד השרת</li>
<li>שליפת נתונים</li>
<li>אופטימיזציות</li>
</ul>
</section>
</main>
);
}
שלב 4 - יצירת דף אודות¶
// app/about/page.tsx
export default function AboutPage() {
return (
<main style={{ padding: "2rem" }}>
<h1>אודות</h1>
<p>אפליקציה זו נבנתה עם Next.js 14 ו-App Router</p>
<p>היא משתמשת ב-Server Components כברירת מחדל</p>
</main>
);
}
- כדי ליצור דף חדש, פשוט יוצרים תיקייה עם קובץ
page.tsx - התיקייה
aboutהופכת אוטומטית לנתיב/about
שרת קומפוננטות לעומת קליינט קומפוננטות - מבט ראשון¶
בנקסט עם App Router, כל הקומפוננטות הן Server Components כברירת מחדל:
// זו Server Component - רצה בשרת
export default function Page() {
console.log("זה ירוץ בשרת, לא בדפדפן!");
return <h1>שלום עולם</h1>;
}
- קוד שרץ בשרת לא נשלח לדפדפן - החבילה קטנה יותר
- אפשר לגשת ישירות לבסיס נתונים, למשתני סביבה רגישים ועוד
- אי אפשר להשתמש ב-hooks כמו useState או useEffect
כדי להשתמש ב-hooks של React, צריך להפוך את הקומפוננטה ל-Client Component:
"use client";
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>ספירה: {count}</p>
<button onClick={() => setCount(count + 1)}>הוסף</button>
</div>
);
}
- ההנחיה
"use client"בתחילת הקובץ הופכת אותו ל-Client Component - נעמיק בנושא הזה בשיעורים הבאים
סיכום¶
- נקסט הוא פריימוורק full-stack מבוסס React שמוסיף ראוטינג, רינדור שרת ואופטימיזציות
- יש ארבע אסטרטגיות רינדור: CSR, SSR, SSG, ISR
- יוצרים פרויקט עם
npx create-next-app@latestובוחרים App Router - מבנה הפרויקט מבוסס על תיקיית
appעם קבציpage.tsxו-layout.tsx - כברירת מחדל כל הקומפוננטות הן Server Components
- פקודות עיקריות:
devלפיתוח,buildלבנייה,startלהרצה בייצור