לדלג לתוכן

9.1 - הקדמה לנקסט - הרצאה

הקדמה לנקסט - Next.js Introduction

בשיעור זה נכיר את Next.js - הפריימוורק המוביל לפיתוח אפליקציות ווב מלאות מבוססות React. נבין למה הוא קיים, מה היתרונות שלו על פני React רגיל, ונלמד ליצור פרויקט ראשון.

מה זה נקסט - Next.js?

  • נקסט הוא פריימוורק מבוסס React שפותח על ידי חברת Vercel
  • הוא מוסיף על React יכולות שלא קיימות בו כברירת מחדל: ראוטינג, רינדור בצד השרת, אופטימיזציות ועוד
  • נקסט הוא פריימוורק full-stack - הוא מאפשר לכתוב גם קוד שרת וגם קוד קליינט בפרויקט אחד

למה לא להשתמש ב-React רגיל?

  • ריאקט לבדו הוא ספרייה לבניית interface משתמש - לא פריימוורק שלם
  • בפרויקט React רגיל (כמו עם Vite) צריך להוסיף בעצמנו ראוטינג, ניהול מטא-דאטה, אופטימיזציות ועוד
  • כל הרינדור קורה בצד הלקוח (CSR) מה שפוגע ב-SEO ובביצועים
  • נקסט פותר את כל הבעיות האלה ונותן פתרון מובנה ומוכן

אסטרטגיות רינדור - Rendering Strategies

אחד הנושאים החשובים ביותר בנקסט הוא הבנת דרכי הרינדור השונות.

רינדור בצד הלקוח - CSR (Client-Side Rendering)

  • זה מה שקורה ב-React רגיל
  • הדפדפן מקבל קובץ HTML ריק ואת קוד ה-JavaScript
  • הדפדפן מריץ את ה-JS ובונה את ה-DOM
  • החיסרון: המשתמש רואה מסך ריק עד שה-JS נטען ורץ
// This is how CSR works - the browser receives almost empty HTML
// <div id="root"></div>
// then React builds all the content in 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)
Request from browser ──> Server runs the code ──> Ready HTML is sent ──> Browser displays immediately

תרשים המשווה בין מסלול הרינדור בצד הלקוח שבו הדפדפן מקבל HTML ריק ובונה את הדף בעצמו לבין מסלול הרינדור בצד השרת שבו מגיע HTML מלא והמשתמש רואה תוכן מיד

יצירת דפים סטטיים - SSG (Static Site Generation)

  • הדפים נבנים בזמן ה-build, לא בזמן הבקשה
  • מתאים לתוכן שלא משתנה לעתים קרובות (בלוג, תיעוד)
  • הכי מהיר - הדפים כבר מוכנים ומוגשים מ-CDN
  • בנקסט עם App Router, זו ברירת המחדל לדפים ללא נתונים דינמיים

רגנרציה סטטית מצטברת - ISR (Incremental Static Regeneration)

  • שילוב של SSG ו-SSR
  • הדף נבנה סטטית, אבל מתעדכן מחדש אחרי זמן מוגדר
  • מתאים לתוכן שמשתנה אבל לא בזמן אמת
// ISR example - the page is revalidated every 60 seconds
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>
  );
}

תרשים זרימה של דף ISR מהיצירה בזמן ה-build דרך בקשות שמקבלות את הדף מהקאש ועד לבקשה שבה פג הזמן והדף נבנה מחדש ברקע

השוואה בין האסטרטגיות

אסטרטגיה זמן רינדור מתאים ל 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        # Root layout - wraps all pages
    page.tsx          # Home page (/)
    globals.css       # Global styles
    favicon.ico       # Site icon
  public/             # Static files (images, fonts)
  next.config.ts      # Next.js config
  tsconfig.json       # TypeScript config
  tailwind.config.ts  # Tailwind config
  package.json        # Dependencies and scripts
  .env.local          # Environment variables (not committed to git)

תיקיית app

  • זו התיקייה המרכזית - כאן חי כל הקוד של האפליקציה
  • כל קובץ page.tsx מייצג דף (route)
  • כל קובץ layout.tsx מגדיר מסגרת לדפים

תיקיית public

  • קבצים סטטיים שזמינים ישירות מהשורש
  • לדוגמה: public/logo.png זמין ב-/logo.png

קובץ הגדרות - next.config.ts

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  // Next.js config here
  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>
  );
}
  • הלייאאוט הראשי חייב להכיל tags <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 כברירת מחדל:

// This is a Server Component - runs on the server
export default function Page() {
  console.log("This will run on the server, not in the browser!");

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