אחסן את חזית וקצה האחורי שלך | מדריך שלב אחר שלב
במדריך זה, נספק מדריך מקיף על אחסון החזית (frontend) והתשתית (backend) של יישום.
לצורך כך, נאחסן אפליקציית Full-Stack ב-Back4app. תחילה נעבוד על ה-backend, לאחר מכן נעבור ל-frontend, ולבסוף נחבר את שני הרכיבים יחד.
Contents
יעדים
בתום מאמר זה, תוכלו:
- להסביר את ההבדלים בין frontend ל-backend
- לבנות backend באמצעות פלטפורמת ה-BaaS של Back4app
- לפרוס אפליקציית frontend ל-Back4app Containers
- לחבר את אפליקציית ה-frontend שלכם עם אפליקציית ה-backend שלכם
מהם ההבדלים בין Frontend ל-Backend?
ה-Backend וה-Frontend מתייחסים להפרדה של תחומי אחריות בעת בניית יישומי ווב ומובייל מודרניים. הדרך הפשוטה ביותר להבין את ההבדלים ביניהם היא לדמיין קרחון.
ה-Frontend (או צד הלקוח) הוא כל מה שהמשתמש יכול לראות ולתקשר איתו. ה-Frontend יכול להופיע בפורמטים שונים, כגון אפליקציות מובייל, אפליקציות ווב, ממשקי רשת או כל סוג אחר של לקוחות.
חלק זה של היישום אחראי על ממשק המשתמש (UI/UX), עיצוב, אנימציות, גרפיקה וסוגים אחרים של מדיה. צד הלקוח מהווה כ-20% מעבודת הפרויקט והוא אינו חוזר על עצמו.
מנגד, ה-Backend (או צד השרת) הוא כל מה שהמשתמש אינו רואה. הוא הגשר בין ה-Frontend לבין מסד הנתונים.
הוא אחראי על הלוגיקה העסקית, משימות רקע, אחסון נתונים, סקיילינג, שילובים עם גורמי צד שלישי וכו’. אף על פי שהמשתמש אינו מתקשר איתו ישירות, יש לו השפעה רבה על איכות היישום.
הוא מהווה כ-80% מעבודת הפרויקט ולעיתים קרובות כולל משימות חוזרות כמו ניהול משתמשים, אימות, הצפנה ועוד.
ניתן לפרוס את אפליקציות ה-Frontend וה-Backend שלכם למגוון פלטפורמות. להלן רשימה של המועדפות האישיות שלי בטבלה הבאה:
פלטפורמות Frontend | פלטפורמות Backend |
---|---|
Back4app Containers | Back4app |
Vercel | Render |
Netlify | Heroku |
GitHub Pages | Linode |
במדריך זה תלמדו כיצד לפרוס את ה-Frontend וה-Backend ל-Back4app — ללא תשלום! המשיכו לקרוא כדי ללמוד כיצד לפרוס Backend ו-Frontend.
הקדמת הפרויקט
הכנתי אפליקציית Full-Stack שתדגים כיצד לפרוס Frontend ו-Backend ל-Back4app.
האפליקציה משמשת כבלוג פשוט המתבסס על Markdown. המנהלים יכולים להוסיף, לערוך ולמחוק מאמרים, בעוד המשתמשים יכולים לקרוא אותם.
הפרויקט הסופי ייראה בערך כך:
כאמור לעיל, האפליקציה מורכבת משני חלקים: Frontend ו-Backend. אם נמחיש את ארכיטקטורת האפליקציה, היא תיראה כך:
נפרוס את ה-Backend ל-Back4app ואת אפליקציית ה-Frontend ל-Back4app Containers. לבסוף, נחבר את שני החלקים דרך Parse SDK.
אני ממליץ לכם קודם כל לעקוב אחר המדריך עם אפליקציה זו ולאחר מכן לבחון את הידע שלכם על ידי פריסה של אפליקציות Full-Stack משלכם.
המשיכו לקרוא כדי ללמוד כיצד לאחסן Backend ו-Frontend.
כיצד לאחסן Backend?
בקטע זה נטפל בחלק ה-Backend של היישום.
מטרות
- לבנות אפליקציה ב-Back4app
- להגדיר את מחלקות בסיס הנתונים
- להגדיר ACLs/CLPs למסד הנתונים
- לאכלס את מסד הנתונים
- להפעיל את Admin App
Create Back4app App
תזדקקו לחשבון Back4app חינמי כדי לעקוב אחר המדריך. אם אינכם רשומים עדיין, הירשמו בחינם!
על מנת לעבוד עם Back4app, תחילה עליכם ליצור אפליקציה. לאחר שתתחברו ל-Back4app, תועברו לדף האפליקציות שלכם. לחצו על הכפתור “Build new app”.
השלב הבא הוא לבחור באפשרות “Backend as a Service” מכיוון שאנו פורסים Backend.
שם את האפליקציה שלכם, בחרו מסד נתונים מסוג “NoSQL” ולחצו על “Create”.
ייקח לפלטפורמה מעט זמן להכין הכול (לדוגמה, מסד הנתונים, סקיילינג, גיבויים ושכבת האפליקציה). בינתיים, תוכלו לקחת הפסקת קפה קצרה.
לאחר שהאפליקציה שלכם תהיה מוכנה, יוצג בפניכם סייר בסיס הנתונים.
Define Database
בקטע זה נתמקד במחלקות של מסד הנתונים.
נזדקק למחלקה אחת בלבד מכיוון שאנו בונים יישום פשוט. לחצו על “Create a class” בסרגל הצד, העניקו לה את השם Article
, השאירו את ההגדרות כברירת מחדל ולחצו “Create class & add columns”.
הוסיפו את חמשת העמודות הבאות למחלקה:
+-----------+--------------+----------------+----------+
| 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 כפי שמוצג בתמונה:
עיינו במאמר הבא כדי ללמוד עוד על אבטחת Parse.
לבסוף, מלאו את מסד הנתונים בכמה דוגמאות של מאמרים.
אם אין לכם רעיונות, תוכלו לייבא את database dump הזה. כדי לייבא אותו, לחצו על האפשרות “More” בחלק העליון הימני של המסך ולאחר מכן “Import > Class Data”, ואז העלו את קובץ ה-JSON.
מצוין, זה הכול!
כעת יש לנו נתוני בדיקה שאפשר לעבוד איתם.
Admin App
כרגע, הדרך היחידה לנהל מאמרים היא דרך סביבת בסיס הנתונים של Back4app. זה לא אידיאלי, משום שאינכם רוצים לשתף פרטי התחברות של Back4app או להוסיף אנשים שאינם טכניים ללוח הבקרה של Back4app.
לשמחתנו, ל-Back4app יש ממשק ניהול דינמי למסדי הנתונים שלכם. כדי להפעיל אותו, בחרו “More > Admin App” בסרגל הצד ולאחר מכן לחצו על “Enable Admin App”.
בחרו שם משתמש, סיסמה וסאב-דומיין ל-Admin App שלכם. לדוגמה:
username: admin
password: verystrongpassword123
admin url: https://fullstack.admin.back4app.com/
עכשיו תוכלו לגשת לפאנל הניהול שלכם בכתובת ה-URL שבחרתם.
פתחו לשונית חדשה ועברו לפאנל הניהול שלכם. הזינו את פרטי ההתחברות ובחנו את הממשק. תוכלו ליצור מאמר, לעדכן אותו ולאחר מכן למחוק אותו.
למידע נוסף על Admin App של Back4app, עיינו בתיעוד.
יצרנו בהצלחה Backend מלא ללא צורך בקוד.
כיצד לאחסן Frontend?
בקטע זה נטפל באפליקציית ה-Frontend.
מטרות
- להגדיר סביבת פיתוח מקומית
- ליצור Docker לאפליקציה (Dockerize)
- לבדוק את תמונות ה-Docker מקומית
- לדחוף את קוד המקור ל-GitHub
- לפרוס את האפליקציה ל-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”.
מכיוון שאנו פורסים אפליקציה Dockerized, בחרו באפשרות “Containers as a Service”.
אם זו הפעם הראשונה שאתם משתמשים ב-Back4app Containers, תתבקשו לחבר את חשבון ה-GitHub שלכם לחשבון Back4app שלכם. ודאו שאתם מאשרים גישה לכל המאגרים שתרצו לפרוס.
בשלב הבא, איתרו את מאגר back4app-full-stack
ולחצו על “Select”.
האפליקציה שאנו פורסים אינה דורשת הגדרה מיוחדת. כל שעליכם לעשות הוא לתת לאפליקציה שם תיאורי. אני בחרתי בשם back4app-full-stack
לצורך סדר.
לבסוף, לחצו על “Deploy”.
Back4app Containers יזדקק למספר דקות כדי לבנות ולפרוס את תמונת ה-Docker שלכם. סטטוס האפליקציה ישתנה ל”Ready” לאחר שהפריסה הצליחה.
כדי לבקר באפליקציה שלכם, לחצו על כתובת ה-URL הירוקה המוצגת בתמונה.
נהדר, פרסתם בהצלחה אפליקציית Frontend ‘דמה’ ל-Back4app Containers.
כיצד לחבר Frontend ל-Backend?
בקטע זה נחבר את ה-Frontend ל-Backend שלנו ב-Back4app.
מטרות
- להתקין Parse SDK
- להגדיר Parse SDK
- לשלוף נתונים (למשל באמצעות
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>
</>
);
}
- קיבלנו את מופע
parse
בעזרתuseContext()
. - יצרנו כמה מצבי state, ביניהם
loading
,error
ו-articles
. - השתמשנו ב-
useEffect()
כדי להריץ אתParse.Query
בעת טעינת הדף. - שאילתת
Parse.Query
מאחזרת את כל המאמרים וממיינת אותם לפיcreatedAt
. - שינינו את פונקציית ההחזרה (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.