לדלג לתוכן

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)
בקשה מהדפדפן ──> השרת מריץ את הקוד ──> HTML מוכן נשלח ──> הדפדפן מציג מיד

יצירת דפים סטטיים - 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

ניצור פרויקט חדש באמצעות הכלי הרשמי של נקסט:

npx create-next-app@latest my-app

בזמן ההתקנה נקבל שאלות:

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 נבחר לפי העדפה

התקנה והרצה

cd my-app
npm run dev
  • שרת הפיתוח ירוץ על 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

הרצת שרת פיתוח

npm run dev
  • מריץ את האפליקציה במצב פיתוח על פורט 3000
  • כולל Hot Module Replacement - שינויים מתעדכנים מיד
  • הודעות שגיאה מפורטות

בנייה לייצור - Build

npm run 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

הרצה בייצור

npm run start
  • מריץ את הגרסה הבנויה (אחרי build)
  • כך זה ירוץ בשרת הייצור

לינט - Lint

npm run lint
  • בודק שגיאות ותקינות קוד עם ESLint
  • נקסט מגיע עם כללי ESLint מובנים

דוגמה מלאה - פרויקט ראשון

ניצור אפליקציה פשוטה עם דף בית ודף אודות:

שלב 1 - יצירת הפרויקט

npx create-next-app@latest my-first-app
cd my-first-app

שלב 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 להרצה בייצור