מדריך Next.JS חלק 4 - חיבור לבסיס נתונים

13/12/2023

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

1. התקנת בסיס נתונים עם Prisma

בשביל הדוגמה בשיעור זה אשתמש בספריית prisma כדי ליצור בסיס נתונים מסוג SQLite לסביבת הפיתוח. בשביל להתקין את פריזמה נלך לפי המדריך כאן:

https://www.prisma.io/docs/getting-started/quickstart

בשלב ראשון נפעיל משורת הפקודה:

npm install typescript ts-node @types/node prisma
npx prisma init --datasource-provider sqlite

לאחר מכן נמצא את תיקיית prisma ובתוכה את הקובץ schema.prisma ונוסיף לסופו את התוכן הבא:

model Post {
  id        Int     @id @default(autoincrement())
  text      String
  author    String
}

לאחר מכן ניצור באותה תיקיה קובץ בשם seed.ts עם התוכן הבא:

import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()

async function main() {
  await prisma.post.create({
    data: {
      author: 'ynonp',
      text: 'hello world'
    }
  })
  await prisma.post.create({
    data: {
      author: 'ynonp',
      text: 'next.js is c00l'
    }
  })
}
main()
  .then(async () => {
    await prisma.$disconnect()
  })
  .catch(async (e) => {
    console.error(e)
    await prisma.$disconnect()
    process.exit(1)
  })

נוסיף לקובץ package.json את הבלוק הבא:

  "prisma": {
    "seed": "ts-node prisma/seed.ts"
  },

ולקובץ tsconfig.json את הבלוק הבא:

  "ts-node": {
    // these options are overrides used only by ts-node
    "compilerOptions": {
      "module": "commonjs"
    }
  },

עכשיו נריץ:

npx prisma migrate dev --name init

ואם הכל הלך כמו שצריך נקבל בתיקיית prisma קובץ בשם dev.db שהוא בסיס נתונים SQLite המכיל טבלא בשם Post עם שתי שורות. אני יכול לוודא את זה משורת הפקודה באופן הבא:

$ sqlite3 prisma/dev.db

SQLite version 3.39.5 2022-10-14 20:58:05
Enter ".help" for usage hints.
sqlite> .tables
Post                _prisma_migrations
sqlite> select * from Post;
1|hello world|ynonp
2|next.js is c00l|ynonp

2. יצירת קומפוננטה להצגת המידע

עכשיו נמשיך לקוד המערכת, וכאן היתרון הגדול של next.js. ניצור תיקיה חדשה בשם posts ובתוכה קובץ בשם page.tsx עם התוכן הבא:

import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()

export default async () => {
  const posts = await prisma.post.findMany();

  return (
    <ul>
      {posts.map(post => (
        <li><b>{post.author}</b> {post.text}</li>
      ))}
    </ul>
  )
}

וזה הכל. גלישה לנתיב:

http://localhost:3000/posts

תציג את רשימת הפוסטים מבסיס הנתונים.

הסיבה שזה עובד היא שהקומפוננטה שלי היא קומפוננטת צד-שרת. לקומפוננטה כזו אין סטייט והיא מרונדרת בצד שרת בלבד. ברינדור בצד השרת אין בעיה לפנות בצורה ישירה לבסיס הנתונים וגם לכלול קריאות ל await בקוד הקומפוננטה, שהפך להיות פונקציה async-ית.

3. עכשיו אתם

  1. לפני הכל בואו נשבור את הקוד שכתבנו - נסו להפוך את הקומפוננטה לקומפוננטת צד-לקוח (עם סטייט) ושימו לב איך אתם כבר לא יכולים לגשת באותה קלות לבסיס הנתונים. אל דאגה, במדריכים הבאים נראה איך לגשת למידע מקומפוננטת צד-לקוח.

  2. יהיה ממש נוח אם התפריט העליון יהיה דינמי ויציג באמת את רשימת הדפים ביישום. אני יודע שכל דף הוא תיקיה על השרת שבתוכה יש קובץ בשם page.tsx. עדכנו את קובץ התפריט, הפכו אותו חזרה ל Server Component וצרו את התפריט בצורה דינמית מתוך התיקיות בפרויקט שמייצגות דפים. וכן אני יודע נצטרך להיפרד מהעיצוב המיוחד ללינק הפעיל ולוותר על usePathname. זאת בעיה אמיתית עם קומפוננטות צד-שרת ויש לה הרבה פיתרונות יצירתיים, אפשר לקרוא עליהם בדיון כאן:

https://github.com/vercel/next.js/issues/43704