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 - בנייה לייצור¶
פלט לדוגמה:
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 נטען בטעינה ראשונה
- במצב ייצור האפליקציה מהירה יותר כי הקוד עבר אופטימיזציה
- ב-development יש Hot Reload ו-error overlay
- ב-production הקוד ממוזער ומותאם לביצועים
תשובות לשאלות¶
-
ההבדל בין CSR ל-SSR: ב-CSR הדפדפן מקבל HTML ריק ובונה את התוכן עם JavaScript. ב-SSR השרת בונה HTML מלא ושולח אותו מוכן. CSR מתאים לדשבורדים ואפליקציות שלא צריכות SEO. SSR מתאים לאתרים שצריכים SEO ותוכן שזמין מיד.
-
יתרון SSG על SSR: ב-SSG הדפים נבנים פעם אחת בזמן ה-build ומוגשים כקבצים סטטיים. זה הרבה יותר מהיר כי אין צורך ליצור את ה-HTML בכל בקשה. בנוסף, אפשר לשרת את הדפים מ-CDN שקרוב למשתמש.
-
למה Server Components כברירת מחדל: הקוד לא נשלח לדפדפן ולכן החבילה קטנה יותר. אפשר לגשת ישירות לבסיס נתונים ולמשאבי שרת. הרינדור קורה בשרת מה שמשפר SEO וביצועים.
-
ההבדל בין layout.tsx ל-page.tsx: קובץ
layout.tsxמגדיר מסגרת שעוטפת דפים - כמו navbar ו-footer. הוא לא מתרנדר מחדש בניווט בין דפים. קובץpage.tsxמגדיר את התוכן הספציפי של כל דף ומשתנה בניווט. -
ההבדל בין app ל-public: תיקיית
appמכילה קוד React שעובר עיבוד - קומפוננטות, לייאאוטים ודפים. תיקייתpublicמכילה קבצים סטטיים (תמונות, פונטים) שמוגשים ישירות ללא עיבוד.