אחסן את חזית וקצה האחורי שלך | מדריך שלב אחר שלב

Back4app Full Stack Application Deploy Cover

במדריך זה, נספק מדריך מקיף על אחסון החזית (frontend) והתשתית (backend) של יישום.

לצורך כך, נאחסן אפליקציית Full-Stack ב-Back4app. תחילה נעבוד על ה-backend, לאחר מכן נעבור ל-frontend, ולבסוף נחבר את שני הרכיבים יחד.

יעדים

בתום מאמר זה, תוכלו:

  • להסביר את ההבדלים בין frontend ל-backend
  • לבנות backend באמצעות פלטפורמת ה-BaaS של Back4app
  • לפרוס אפליקציית frontend ל-Back4app Containers
  • לחבר את אפליקציית ה-frontend שלכם עם אפליקציית ה-backend שלכם

מהם ההבדלים בין Frontend ל-Backend?

ה-Backend וה-Frontend מתייחסים להפרדה של תחומי אחריות בעת בניית יישומי ווב ומובייל מודרניים. הדרך הפשוטה ביותר להבין את ההבדלים ביניהם היא לדמיין קרחון.

Backend vs Frontend

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

חלק זה של היישום אחראי על ממשק המשתמש (UI/UX), עיצוב, אנימציות, גרפיקה וסוגים אחרים של מדיה. צד הלקוח מהווה כ-20% מעבודת הפרויקט והוא אינו חוזר על עצמו.

מנגד, ה-Backend (או צד השרת) הוא כל מה שהמשתמש אינו רואה. הוא הגשר בין ה-Frontend לבין מסד הנתונים.

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

הוא מהווה כ-80% מעבודת הפרויקט ולעיתים קרובות כולל משימות חוזרות כמו ניהול משתמשים, אימות, הצפנה ועוד.

ניתן לפרוס את אפליקציות ה-Frontend וה-Backend שלכם למגוון פלטפורמות. להלן רשימה של המועדפות האישיות שלי בטבלה הבאה:

פלטפורמות Frontendפלטפורמות Backend
Back4app ContainersBack4app
VercelRender
NetlifyHeroku
GitHub PagesLinode

במדריך זה תלמדו כיצד לפרוס את ה-Frontend וה-Backend ל-Back4app — ללא תשלום! המשיכו לקרוא כדי ללמוד כיצד לפרוס Backend ו-Frontend.

הקדמת הפרויקט

הכנתי אפליקציית Full-Stack שתדגים כיצד לפרוס Frontend ו-Backend ל-Back4app.

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

הפרויקט הסופי ייראה בערך כך:

Back4app Full-Stack App Blog

כאמור לעיל, האפליקציה מורכבת משני חלקים: Frontend ו-Backend. אם נמחיש את ארכיטקטורת האפליקציה, היא תיראה כך:

Back4app Full-Stack App Architecture

נפרוס את ה-Backend ל-Back4app ואת אפליקציית ה-Frontend ל-Back4app Containers. לבסוף, נחבר את שני החלקים דרך Parse SDK.

אני ממליץ לכם קודם כל לעקוב אחר המדריך עם אפליקציה זו ולאחר מכן לבחון את הידע שלכם על ידי פריסה של אפליקציות Full-Stack משלכם.

המשיכו לקרוא כדי ללמוד כיצד לאחסן Backend ו-Frontend.

כיצד לאחסן Backend?

בקטע זה נטפל בחלק ה-Backend של היישום.

מטרות

  1. לבנות אפליקציה ב-Back4app
  2. להגדיר את מחלקות בסיס הנתונים
  3. להגדיר ACLs/CLPs למסד הנתונים
  4. לאכלס את מסד הנתונים
  5. להפעיל את Admin App

Create Back4app App

תזדקקו לחשבון Back4app חינמי כדי לעקוב אחר המדריך. אם אינכם רשומים עדיין, הירשמו בחינם!

על מנת לעבוד עם Back4app, תחילה עליכם ליצור אפליקציה. לאחר שתתחברו ל-Back4app, תועברו לדף האפליקציות שלכם. לחצו על הכפתור “Build new app”.

Back4app Create App

השלב הבא הוא לבחור באפשרות “Backend as a Service” מכיוון שאנו פורסים Backend.

Back4app Backend as a Service

שם את האפליקציה שלכם, בחרו מסד נתונים מסוג “NoSQL” ולחצו על “Create”.

Back4app BaaS Configuration

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

לאחר שהאפליקציה שלכם תהיה מוכנה, יוצג בפניכם סייר בסיס הנתונים.

Back4app Database View

Define Database

בקטע זה נתמקד במחלקות של מסד הנתונים.

נזדקק למחלקה אחת בלבד מכיוון שאנו בונים יישום פשוט. לחצו על “Create a class” בסרגל הצד, העניקו לה את השם Article, השאירו את ההגדרות כברירת מחדל ולחצו “Create class & add columns”.

Back4app Create Database Class

הוסיפו את חמשת העמודות הבאות למחלקה:

+-----------+--------------+----------------+----------+
| Data type | Name         | Default value  | Required |
+-----------+--------------+----------------+----------+
| String    | slug         | <leave blank>  | 1        |
+-----------+--------------+----------------+----------+
| String    | title        | <leave blank>  | 1        |
+-----------+--------------+----------------+----------+
| File      | cover        | <leave blank>  | 0        |
+-----------+--------------+----------------+----------+
| String    | shortContent | <leave blank>  | 1        |
+-----------+--------------+----------------+----------+
| String    | content      | <leave blank>  | 1        |
+-----------+--------------+----------------+----------+

זכרו להוסיף עמודות נוספות לכל מידע נוסף שתרצו לשמור.

ברירת המחדל של מחלקות בסיס הנתונים היא “Protected mode”. אם אנו רוצים לעבוד איתן מתוך אפליקציית ה-Frontend, עלינו לשנות מעט את הגדרות ה-CLPs (הרשאות ברמת המחלקה). לחצו על סמל המנעול בחלק העליון של המסך ושנו את ה-CLPs כפי שמוצג בתמונה:

Back4app Class CLPs

עיינו במאמר הבא כדי ללמוד עוד על אבטחת Parse.

לבסוף, מלאו את מסד הנתונים בכמה דוגמאות של מאמרים.

אם אין לכם רעיונות, תוכלו לייבא את database dump הזה. כדי לייבא אותו, לחצו על האפשרות “More” בחלק העליון הימני של המסך ולאחר מכן “Import > Class Data”, ואז העלו את קובץ ה-JSON.

Back4app Database Populated

מצוין, זה הכול!

כעת יש לנו נתוני בדיקה שאפשר לעבוד איתם.

Admin App

כרגע, הדרך היחידה לנהל מאמרים היא דרך סביבת בסיס הנתונים של Back4app. זה לא אידיאלי, משום שאינכם רוצים לשתף פרטי התחברות של Back4app או להוסיף אנשים שאינם טכניים ללוח הבקרה של Back4app.

לשמחתנו, ל-Back4app יש ממשק ניהול דינמי למסדי הנתונים שלכם. כדי להפעיל אותו, בחרו “More > Admin App” בסרגל הצד ולאחר מכן לחצו על “Enable Admin App”.

Back4app Enable Admin App

בחרו שם משתמש, סיסמה וסאב-דומיין ל-Admin App שלכם. לדוגמה:

username:     admin
password:     verystrongpassword123
admin url:    https://fullstack.admin.back4app.com/

עכשיו תוכלו לגשת לפאנל הניהול שלכם בכתובת ה-URL שבחרתם.

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

Back4app Admin App Dashboard

למידע נוסף על Admin App של Back4app, עיינו בתיעוד.

יצרנו בהצלחה Backend מלא ללא צורך בקוד.

כיצד לאחסן Frontend?

בקטע זה נטפל באפליקציית ה-Frontend.

מטרות

  1. להגדיר סביבת פיתוח מקומית
  2. ליצור Docker לאפליקציה (Dockerize)
  3. לבדוק את תמונות ה-Docker מקומית
  4. לדחוף את קוד המקור ל-GitHub
  5. לפרוס את האפליקציה ל-Back4app Containers

Local Setup

התחילו ב-fork של כל הסניפים (branches) של מאגר זה ואז שבטו (clone) את ה-fork למחשב המקומי שלכם:

$ git clone <fork_remote_git_url> --branch dummy
$ cd back4app-heroku-deploy && git branch -m master

שיבטנו את הסניף dummy משום שהוא אינו כולל את קוד ה-backend. נעסוק בקוד ה-backend בסעיף הבא.

לאחר מכן, התקינו את התלויות של הפרויקט:

$ npm install

לבסוף, הפעילו את שרת הפיתוח:

$ npm run dev

פתחו את הדפדפן המועדף עליכם ועברו לכתובת http://localhost:3000. עליכם לראות את דף האינדקס של הבלוג. נסו ללחוץ על מאמר כדי לבדוק אם אתם מועברים לעמוד פרטי המאמר.

נכון לעכשיו, עמוד פרטי המאמר מקודד קשיח (hard-coded). אל דאגה, נטפל בכך בהמשך.

Dockerize

כדי לפרוס אפליקציה ל-Back4app Containers, תחילה עלינו ליצור לה Docker.

יצירת Docker (Dockerization) היא התהליך של אריזת הקוד בתוך קונטיינר שניתן לפרוס לכל מקום. הדרך הקלה ביותר לבצע זאת היא בעזרת קובץ Dockerfile.

Dockerfile

קובץ Dockerfile מכיל הנחיות ליצירת תמונת Docker Container. באמצעות קובץ זה תוכלו להגדיר את הסביבה, להתקין תלויות ולהריץ פקודות הנדרשות לצורך בנייה והפעלה של האפליקציה.

צרו קובץ בשם Dockerfile בספריית השורש של הפרויקט והדביקו בתוכו את התוכן הבא:

# Dockerfile

FROM node:18-alpine

WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .

RUN npm run build
RUN npm install -g next

EXPOSE 3000

CMD ["next", "start", "-p", "3000"]

קובץ Dockerfile זה מבוסס על התמונה node:18-alpine. הוא מגדיר את ספריית העבודה, מטפל בתלויות, מעתיק את הפרויקט ובונה את האפליקציה.

לאחר שהאפליקציה בנויה, הוא פותח את פורט 3000 ומפעיל שרת Next.js שמאזין עליו.

כדי ללמוד עוד על Dockerfile, עיינו בתיעוד הרשמי.

.dockerignore

גודל תמונת Docker כדאי לצמצם ככל האפשר. הדרך הפשוטה ביותר לעשות זאת היא על ידי יצירת קובץ בשם .dockerignore. קובץ זה מאפשר לכם לקבוע אילו קבצים ותיקיות לא ייכללו בתמונת ה-Docker הסופית.

לדוגמה, אינכם רוצים לכלול קבצי IDE, תיקיית build, .git או node_modules בתוך התמונה.

הנה דוגמה לקובץ .dockerignore שתוכלו להשתמש בה:

# .dockerignore

.idea/

/node_modules
/.next/
/out/
/build

.vercel

דאגו להתאים את קובץ .dockerignore בהתאם לצרכיכם.

Build, run, test

תמיד כדאי לבדוק את פרויקט ה-Docker שלכם בסביבה מקומית לפני שאתם דוחפים אותו לענן. הדרך הקלה ביותר לבדוק את ה-Dockerfile היא באמצעות Docker Desktop.

לאחר ההתקנה, תוכלו לבנות את התמונה שלכם באמצעות הפקודה הבאה:

$ docker build -t blog-frontend:1.0 .

הציגו את רשימת התמונות כדי לבדוק שהתמונה נוצרה בהצלחה:

$ docker images

REPOSITORY        TAG       IMAGE ID       CREATED             SIZE
blog-frontend     1.0       d361534a68da   2 minutes ago       1.08GB

הריצו קונטיינר באמצעות התמונה שזה עתה בניתם:

$ docker run -p 3000:3000 --name blog-frontend blog-frontend:1.0

פתחו את הדפדפן המועדף עליכם ועברו לכתובת http://localhost:3000. עליכם לראות שם את האפליקציה שלכם!

כדי לעצור את הקונטיינר, הקישו CTRL + c במקלדת.

Push to GitHub

Back4app Containers משולב היטב עם GitHub ומספק מערכת CI/CD אוטומטית שתפרוס מחדש את האפליקציה עם כל קומיט חדש. כדי לפרוס את הקוד בסעיף הבא, עליכם תחילה לדחוף את השינויים למערכת בקרת הגרסאות (VCS).

בצעו commit לכל השינויים ודחפו אותם לענן:

$ git add .
$ git commit -m "dockerized the application"
$ git push origin master

עברו למאגר (repo) שלכם ב-GitHub וודאו שקובץ Dockerfile קיים במאגר.

Deploy App

תזדקקו לחשבון Back4app בחינם כדי לעקוב אחר השלבים. אם עדיין לא נרשמתם, הירשמו בחינם!

התחילו בכך שתעברו ללוח הבקרה שלכם ב-Back4app ולחצו על “Build new app”.

Back4app Create Application

מכיוון שאנו פורסים אפליקציה Dockerized, בחרו באפשרות “Containers as a Service”.

Back4app Select CaaS

אם זו הפעם הראשונה שאתם משתמשים ב-Back4app Containers, תתבקשו לחבר את חשבון ה-GitHub שלכם לחשבון Back4app שלכם. ודאו שאתם מאשרים גישה לכל המאגרים שתרצו לפרוס.

בשלב הבא, איתרו את מאגר back4app-full-stack ולחצו על “Select”.

Back4app Select GitHub Repository

האפליקציה שאנו פורסים אינה דורשת הגדרה מיוחדת. כל שעליכם לעשות הוא לתת לאפליקציה שם תיאורי. אני בחרתי בשם back4app-full-stack לצורך סדר.

לבסוף, לחצו על “Deploy”.

Back4app Containers Environment

Back4app Containers יזדקק למספר דקות כדי לבנות ולפרוס את תמונת ה-Docker שלכם. סטטוס האפליקציה ישתנה ל”Ready” לאחר שהפריסה הצליחה.

כדי לבקר באפליקציה שלכם, לחצו על כתובת ה-URL הירוקה המוצגת בתמונה.

Back4app Successful Deployment

נהדר, פרסתם בהצלחה אפליקציית Frontend ‘דמה’ ל-Back4app Containers.

כיצד לחבר Frontend ל-Backend?

בקטע זה נחבר את ה-Frontend ל-Backend שלנו ב-Back4app.

מטרות

  1. להתקין Parse SDK
  2. להגדיר Parse SDK
  3. לשלוף נתונים (למשל באמצעות Parse.Query)

Install Parse SDK

תחילה, התקינו את Parse SDK:

$ npm install parse

Configure Parse SDK

כדי לאתחל את Parse SDK, יהיה עליכם להזין את מזהה האפליקציה (Application ID) ואת מפתח ה-JavaScript (JavaScript key) של Back4app שלכם. כדי להשיג אותם, עברו לאפליקציית Back4app שלכם ובחרו “App Settings > Security & Keys” בסרגל הצד.

מכיוון שאיננו רוצים לחשוף פרטי גישה אלו בקוד המקור, צרו קובץ .env.local:

# .env.local

NEXT_PUBLIC_PARSE_APPLICATION_ID=<your_parse_app_id>
NEXT_PUBLIC_PARSE_JAVASCRIPT_KEY=<your_parse_js_key>

ודאו שאתם מחליפים את הערכים המוצגים בדוגמה בערכי האמת שלכם.

Initialize Parse SDK

בשלב הבא, עברו לקובץ providers.js שלכם ואתחלו את Parse בצורה הבאה:

// src/app/providers.js

// ...

import Parse from "parse/dist/parse";

const PARSE_APPLICATION_ID = process.env.NEXT_PUBLIC_PARSE_APPLICATION_ID;
const PARSE_JAVASCRIPT_KEY = process.env.NEXT_PUBLIC_PARSE_JAVASCRIPT_KEY;
Parse.initialize(PARSE_APPLICATION_ID, PARSE_JAVASCRIPT_KEY);
Parse.serverURL = "https://parseapi.back4app.com/";

export function Providers({children}) {
    return (
        // ...
    );
}

על מנת לגשת ל-Parse בכל רכיבי הממשק שלנו, נשתמש ב-React context.

צרו קובץ חדש בשם context/parseContext.js והדביקו את הקוד הבא בתוכו:

// src/app/context/parseContext.js

"use client";

import {createContext} from "react";

const ParseContext = createContext();

export default ParseContext;

לאחר מכן, עטפו את כל האפליקציה שלכם עם ParseContext והעבירו לו את מופע ה-Parse:

// src/app/providers.js

// ...

import ParseContext from "@/app/context/parseContext";

export function Providers({children}) {
  return (
    <CacheProvider>
      <ColorModeScript initialColorMode={theme.config.initialColorMode} />
      <ChakraProvider theme={theme}>
        <ParseContext.Provider value={Parse}>
          {children}
        </ParseContext.Provider>
      </ChakraProvider>
    </CacheProvider>
  );
}

זהו! כעת נוכל לגשת למופע של Parse באמצעות ה-hook useContext().

Fetch Data

הדבר האחרון שנותר לנו הוא לשלוף נתונים מה-Backend. לשם כך נשתמש ב-Parse.Query. מחלקה זו משמשת למעשה כ-ORM עבור מסדי נתונים מבוססי Parse.

קודם, החליפו את התוכן של src/app/page.jsx בתוכן הבא:

// src/app/page.jsx

"use client";

import NextLink from "next/link";
import {useContext, useEffect, useState} from "react";
import ParseContext from "@/app/context/parseContext";
import {Card, CardBody, Heading, Link, Spinner, Stack, Text} from "@chakra-ui/react";

export default function Home() {

  const parse = useContext(ParseContext);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");

  const [articles, setArticles] = useState([]);

  useEffect(() => {
    (async () => {
      try {
        const query = new parse.Query("Article");
        query.descending("createdAt");
        const articles = await query.find();
        setArticles(articles);
      } catch (error) {
        setError(error);
      } finally {
        setLoading(false);
      }
    })();
  }, [parse.Query]);

  if (loading) {
    return <Spinner size="lg"/>;
  }

  if (error) {
    return <Text color="red">{error}</Text>;
  }

  return (
    <>
      <Stack>
        {articles.map((article) => (
          <Card key={article.get("slug")}>
            <CardBody>
              <Stack>
                <Heading size="lg">
                  <Link as={NextLink} href={article.get("slug")}>
                    {article.get("title")}
                  </Link>
                </Heading>
                <Text>{article.get("shortContent")}</Text>
              </Stack>
            </CardBody>
          </Card>
        ))}
      </Stack>
    </>
  );
}
  1. קיבלנו את מופע parse בעזרת useContext().
  2. יצרנו כמה מצבי state, ביניהם loading, error ו-articles.
  3. השתמשנו ב-useEffect() כדי להריץ את Parse.Query בעת טעינת הדף.
  4. שאילתת Parse.Query מאחזרת את כל המאמרים וממיינת אותם לפי createdAt.
  5. שינינו את פונקציית ההחזרה (return) כדי להציג את הנתונים.

לאחר מכן החליפו את התוכן של src/app/[slug]/page.js בזה:

// src/app/[slug]/page.js

"use client";

import {formatDate} from "@/app/util/date-util";
import {useContext, useEffect, useState} from "react";
import ParseContext from "@/app/context/parseContext";
import {Card, CardBody, Heading, Image, Spinner, Stack, Text} from "@chakra-ui/react";
import ReactMarkdown from "react-markdown";
import ChakraUIRenderer from "chakra-ui-markdown-renderer";

export default function Article({params}) {

  const parse = useContext(ParseContext);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");

  const [article, setArticle] = useState(null);

  useEffect(() => {
    (async () => {
      try {
        const query = new parse.Query("Article");
        query.equalTo("slug", params.slug);
        const article = await query.first();
        if (!article) {
          setError("This article does not exist.");
        } else {
          setArticle(article);
        }
      } catch (error) {
        setError(error);
      } finally {
        setLoading(false);
      }
    })();
  }, [params.slug, parse.Query]);

  if (loading) {
    return <Spinner size="lg"/>;
  }

  if (error) {
    return <Text color="red">{error}</Text>;
  }

  return (
    <>
      {article && (
        <Stack>
          <Card>
            <CardBody>
              <Stack>
                <Heading as="h2" size="lg">{article.get("title")}</Heading>
                <Text>Posted on {formatDate(article.get("createdAt"))}</Text>
                {article.get("cover") && (
                  <Image 
                      src={article.get("cover").url()} 
                      alt={`${article.get("title")} cover`} 
                      borderRadius="lg"
                  />
                )}
                <ReactMarkdown 
                    components={ChakraUIRenderer()} 
                    children={article.get("content")} 
                    skipHtml
                />
              </Stack>
            </CardBody>
          </Card>
        </Stack>
      )}
    </>
  );
}

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

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

$ next dev

לאחר שאתם בטוחים שהכול פועל כשורה, דחפו את השינויים למערכת ה-VCS:

$ git add .
$ git commit -m "connected the frontend with the backend"
$ git push origin master

Back4app Containers תפרוס מחדש את האפליקציה שלכם אוטומטית עם השינויים האחרונים.

סיכום

לסיכום, הצלחנו לפרוס אפליקציית Full-Stack ב-Back4app. בתהליך זה רכשתם ניסיון חשוב בנושא אחסון החזית והתשתית של אפליקציה. כעת לא אמורה להיות לכם בעיה לפרוס אפליקציות Full-Stack משלכם.

קוד המקור הסופי זמין במאגר back4app-full-stack, וכעת אתם יודעים היכן ניתן לאחסן Frontend ו-Backend.


Leave a reply

Your email address will not be published.