לדלג לתוכן

9.1 הקדמה לנקסט פתרון

פתרון - הקדמה לנקסט - Next.js Introduction

פתרון תרגיל 1 - יצירת פרויקט

יצירת הפרויקט:

npx create-next-app@latest my-portfolio
# בוחרים: TypeScript, ESLint, Tailwind, App Router
cd my-portfolio
npm run dev

דף הבית המעודכן:

// app/page.tsx
export default function HomePage() {
  return (
    <main className="p-8">
      <h1 className="text-4xl font-bold mb-4">ישראל ישראלי</h1>
      <p className="text-lg mb-6">
        מפתח פול-סטאק עם ניסיון בפיתוח אפליקציות ווב
      </p>

      <h2 className="text-2xl font-semibold mb-3">טכנולוגיות</h2>
      <ul className="list-disc list-inside space-y-1">
        <li>React ו-Next.js</li>
        <li>TypeScript</li>
        <li>Node.js</li>
      </ul>
    </main>
  );
}

פתרון תרגיל 2 - מבנה הפרויקט

דף אודות:

// app/about/page.tsx
export default function AboutPage() {
  return (
    <main className="p-8">
      <h1 className="text-3xl font-bold mb-4">אודות</h1>
      <p>שמי ישראל ישראלי, מפתח תוכנה עם תשוקה לטכנולוגיה.</p>
      <p className="mt-2">
        אני מתמחה בפיתוח אפליקציות ווב מודרניות עם React ו-Next.js.
      </p>
    </main>
  );
}

דף פרויקטים:

// app/projects/page.tsx
export default function ProjectsPage() {
  return (
    <main className="p-8">
      <h1 className="text-3xl font-bold mb-4">פרויקטים</h1>
      <div className="space-y-4">
        <div className="border p-4 rounded">
          <h2 className="text-xl font-semibold">אפליקציית משימות</h2>
          <p>אפליקציה לניהול משימות יומיות</p>
        </div>
        <div className="border p-4 rounded">
          <h2 className="text-xl font-semibold">בלוג אישי</h2>
          <p>בלוג עם מערכת ניהול תוכן</p>
        </div>
      </div>
    </main>
  );
}

דף יצירת קשר:

// app/contact/page.tsx
export default function ContactPage() {
  return (
    <main className="p-8">
      <h1 className="text-3xl font-bold mb-4">יצירת קשר</h1>
      <p>ניתן ליצור איתי קשר בדרכים הבאות:</p>
      <ul className="list-disc list-inside mt-2">
        <li>אימייל: israel@example.com</li>
        <li>לינקדאין: linkedin.com/in/israel</li>
        <li>גיטהאב: github.com/israel</li>
      </ul>
    </main>
  );
}

פתרון תרגיל 3 - לייאאוט ראשי עם ניווט

// 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 className="min-h-screen flex flex-col">
        <nav className="bg-gray-800 text-white p-4">
          <div className="max-w-4xl mx-auto flex gap-6">
            <a href="/" className="hover:text-gray-300">
              בית
            </a>
            <a href="/about" className="hover:text-gray-300">
              אודות
            </a>
            <a href="/projects" className="hover:text-gray-300">
              פרויקטים
            </a>
            <a href="/contact" className="hover:text-gray-300">
              יצירת קשר
            </a>
          </div>
        </nav>

        <main className="flex-1">{children}</main>

        <footer className="bg-gray-100 p-4 text-center text-gray-600">
          <p>כל הזכויות שמורות - ישראל ישראלי 2024</p>
        </footer>
      </body>
    </html>
  );
}
  • הלייאאוט עוטף את כל הדפים - ה-navbar וה-footer מופיעים בכל דף
  • הגדרנו lang="he" ו-dir="rtl" לעברית
  • הוספנו metadata עם כותרת ותיאור

פתרון תרגיל 4 - הבנת סוגי רינדור

// app/render-demo/page.tsx
export default function RenderDemo() {
  const now = new Date().toLocaleString("he-IL");
  console.log("הקומפוננטה רנדרה ב:", now);

  return (
    <main className="p-8">
      <h1 className="text-3xl font-bold mb-4">הדגמת רינדור</h1>
      <p className="text-lg">תאריך ושעה: {now}</p>
      <p className="mt-2 text-gray-600">
        בדקו בטרמינל ובקונסולה של הדפדפן - איפה ההודעה מופיעה?
      </p>
    </main>
  );
}
  • בלי "use client" - זו Server Component. ה-console.log מופיע בטרמינל של השרת, לא בדפדפן
  • עם "use client" - זו Client Component. ה-console.log מופיע בקונסולה של הדפדפן
  • ב-Server Component, התאריך מחושב בשרת. ב-Client Component, הוא מחושב בדפדפן

פתרון תרגיל 5 - קובץ הגדרות

// next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: "https",
        hostname: "images.unsplash.com",
      },
    ],
  },

  async redirects() {
    return [
      {
        source: "/home",
        destination: "/",
        permanent: true,
      },
    ];
  },
};

export default nextConfig;
  • remotePatterns מאפשר לנקסט לבצע אופטימיזציה לתמונות מדומיינים חיצוניים
  • permanent: true מחזיר קוד 308 (redirect קבוע) - הדפדפן יזכור את ההפניה

פתרון תרגיל 6 - בנייה לייצור

npm run build

פלט לדוגמה:

Route (app)              Size     First Load JS
  /                      2.1 kB   85.2 kB
  /about                 512 B    83.6 kB
  /contact               520 B    83.6 kB
  /projects              890 B    83.9 kB
  /render-demo           450 B    83.5 kB

○  (Static)   prerendered as static content
  • הסימן מציין שהדף נבנה כסטטי (SSG) - זו ברירת המחדל
  • First Load JS מראה כמה JS נטען בטעינה ראשונה
  • במצב ייצור האפליקציה מהירה יותר כי הקוד עבר אופטימיזציה
npm run start
  • ב-development יש Hot Reload ו-error overlay
  • ב-production הקוד ממוזער ומותאם לביצועים

תשובות לשאלות

  1. ההבדל בין CSR ל-SSR: ב-CSR הדפדפן מקבל HTML ריק ובונה את התוכן עם JavaScript. ב-SSR השרת בונה HTML מלא ושולח אותו מוכן. CSR מתאים לדשבורדים ואפליקציות שלא צריכות SEO. SSR מתאים לאתרים שצריכים SEO ותוכן שזמין מיד.

  2. יתרון SSG על SSR: ב-SSG הדפים נבנים פעם אחת בזמן ה-build ומוגשים כקבצים סטטיים. זה הרבה יותר מהיר כי אין צורך ליצור את ה-HTML בכל בקשה. בנוסף, אפשר לשרת את הדפים מ-CDN שקרוב למשתמש.

  3. למה Server Components כברירת מחדל: הקוד לא נשלח לדפדפן ולכן החבילה קטנה יותר. אפשר לגשת ישירות לבסיס נתונים ולמשאבי שרת. הרינדור קורה בשרת מה שמשפר SEO וביצועים.

  4. ההבדל בין layout.tsx ל-page.tsx: קובץ layout.tsx מגדיר מסגרת שעוטפת דפים - כמו navbar ו-footer. הוא לא מתרנדר מחדש בניווט בין דפים. קובץ page.tsx מגדיר את התוכן הספציפי של כל דף ומשתנה בניווט.

  5. ההבדל בין app ל-public: תיקיית app מכילה קוד React שעובר עיבוד - קומפוננטות, לייאאוטים ודפים. תיקיית public מכילה קבצים סטטיים (תמונות, פונטים) שמוגשים ישירות ללא עיבוד.