از FARM Stack برای توسعه برنامه های Full Stack استفاده کنید
پشته FARM یک پشته توسعه وب مدرن است که چهار فناوری قدرتمند را ترکیب می کند: FastAPI، React و MongoDB. این راه حل تمام پشته مجموعه ای قوی از ابزارها را برای ایجاد برنامه های کاربردی وب مقیاس پذیر، کارآمد و با کارایی بالا در اختیار توسعه دهندگان قرار می دهد.
در این مقاله، هر یک از فناوریهای کلیدی را به شما معرفی میکنم و سپس با استفاده از FARM stack و Docker پروژهای میسازیم تا بتوانید ببینید که چگونه همه چیز با هم کار میکند.
این مقاله بر اساس دوره ای است که من در کانال YouTube freeCodeCamp.org ایجاد کردم. اینجا را تماشا کنید:
مقدمه ای بر FARM Stack
پشته FARM در FARM مخفف:
F: FastAPI (Backend)
R: React (Frontend)
M: MongoDB (پایگاه داده)
پشته FARM به گونه ای طراحی شده است که از نقاط قوت هر مؤلفه استفاده کند و به توسعه دهندگان این امکان را می دهد تا برنامه های کاربردی غنی از ویژگی ها را با تجربه توسعه روان ایجاد کنند.
اجزای FARM Stack
FastAPI: FastAPI یک چارچوب وب پایتون مدرن و با کارایی بالا برای ساخت API است. این به گونه ای طراحی شده است که استفاده از آن آسان، کدنویسی سریع و آماده برای محیط های تولید باشد. FastAPI در بالای Starlette برای بخشهای وب و Pydantic برای بخشهای داده ساخته شده است، که آن را به یک انتخاب قدرتمند برای ایجاد خدمات باطن قوی تبدیل میکند.
React : React یک کتابخانه محبوب جاوا اسکریپت برای ساخت رابط کاربری است. React که توسط فیسبوک توسعه و نگهداری میشود، به توسعهدهندگان اجازه میدهد تا اجزای رابط کاربری قابل استفاده مجدد را ایجاد کنند که بهطور مؤثری بهروزرسانی و با تغییر دادهها ارائه شوند. معماری مبتنی بر کامپوننت و DOM مجازی آن را به انتخابی عالی برای ساخت برنامههای ظاهری پویا و پاسخگو تبدیل کرده است.
MongoDB: MongoDB یک پایگاه داده NoSQL سند گرا است. این داده ها را در اسناد منعطف و JSON مانند ذخیره می کند، به این معنی که فیلدها می توانند از سندی به سند دیگر متفاوت باشند و ساختار داده ها را می توان در طول زمان تغییر داد. این انعطافپذیری، MongoDB را به گزینهای ایدهآل برای برنامههایی تبدیل میکند که نیاز به تکامل سریع و مدیریت انواع دادههای مختلف دارند.
مزایای استفاده از FARM Stack
عملکرد بالا: FastAPI یکی از سریعترین چارچوبهای پایتون موجود است، در حالی که DOM مجازی React بهروزرسانیهای کارآمد UI را تضمین میکند. مدل سند MongoDB امکان خواندن و نوشتن سریع را فراهم می کند.
مقیاس پذیری: همه اجزای پشته FARM به گونه ای طراحی شده اند که مقیاس شوند. FastAPI میتواند درخواستهای همزمان را بهطور مؤثر مدیریت کند، برنامههای React میتوانند رابطهای کاربری پیچیده را مدیریت کنند، و MongoDB میتواند دادهها را در چندین سرور توزیع کند.
جامعه و اکوسیستم: هر سه فناوری دارای جوامع بزرگ و فعال و اکوسیستم های غنی از کتابخانه ها و ابزار هستند.
انعطاف پذیری: پشته FARM به اندازه کافی منعطف است تا انواع مختلفی از برنامه های کاربردی وب را در خود جای دهد، از برنامه های ساده CRUD تا سیستم های پیچیده و فشرده داده.
با ترکیب این فناوری ها، پشته FARM راه حلی جامع برای ساخت برنامه های کاربردی وب مدرن ارائه می دهد. این به توسعهدهندگان اجازه میدهد با FastAPI بکاندهای سریع و مقیاسپذیر، فرانتاندهای بصری و پاسخگو با React و ذخیرهسازی دادههای انعطافپذیر و کارآمد با MongoDB ایجاد کنند. این پشته مخصوصاً برای برنامههایی که به بهروزرسانیهای بلادرنگ، مدلهای داده پیچیده و عملکرد بالا نیاز دارند، مناسب است.
نمای کلی پروژه: برنامه Todo
در دوره ویدیویی، من بیشتر در مورد هر یک از فناوریهای موجود در FARM Stack توضیح میدهم. اما در این مقاله، ما میخواهیم به پروژهای بپردازیم تا همه چیز را کنار هم بگذاریم.
ما یک برنامه todo ایجاد خواهیم کرد تا به ما در درک پشته FARM کمک کند. قبل از شروع ساخت اپلیکیشن، اجازه دهید در مورد ویژگی ها و معماری نرم افزار بیشتر بحث کنیم.
ویژگی های برنامه todo
برنامه FARM stack todo ما شامل ویژگی های زیر خواهد بود:
چند فهرست کارها:
کاربران می توانند چندین فهرست کار را ایجاد، مشاهده، به روز رسانی و حذف کنند.
هر فهرست یک نام دارد و شامل چندین مورد برای انجام کار است.
موارد کار:
در هر فهرست ، کاربران می توانند موارد انجام کار را اضافه، مشاهده، به روز رسانی و حذف کنند.
هر آیتم دارای یک برچسب، یک وضعیت علامت زده/بدون علامت است و به یک فهرست خاص تعلق دارد.
به روز رسانی در زمان واقعی:
هنگامی که تغییراتی در فهرست ها یا موارد ایجاد می شود، رابط کاربری در زمان واقعی به روز می شود.
طراحی واکنشگرا:
این برنامه واکنش گرا خواهد بود و به خوبی در دستگاه های دسکتاپ و تلفن همراه کار می کند.
معماری سیستم
برنامه todo ما از معماری پشته FARM معمولی پیروی می کند:
Frontend (React):
رابط کاربری را برای تعامل با فهرست ها و موارد انجام کار فراهم میکند.
از طریق تماس های RESTful API با backend ارتباط برقرار می کند.
Backend (FastAPI):
رسیدگی به درخواست های API از فرانت اند.
منطق کسب و کار را برای مدیریت فهرست ها و موارد انجام کار پیاده سازی می کند.
برای تداوم داده ها با پایگاه داده MongoDB تعامل دارد.
پایگاه داده (MongoDB):
فهرست ها و اقلام کار را ذخیره می کند.
پرس و جو و به روز رسانی کارآمد داده های todo را فراهم می کند.
داکر:
برای توسعه و استقرار آسان هر مؤلفه (فرانت اند، باطن، پایگاه داده) را کانتینر می کند.
طراحی مدل داده
مدل داده MongoDB ما از دو ساختار اصلی تشکیل شده است:
فهرست کارها:
{ "_id" : ObjectId, "name" : String, "items" : [ { "id" : String, "label" : String, "checked" : Boolean } ] }
خلاصه فهرست (برای نمایش در فهرست همه فهرست های کار):
{ "_id" : ObjectId, "name" : String, "item_count" : Integer }
طراحی نقطه پایانی API
باطن FastAPI ما نقاط پایانی RESTful زیر را در معرض دید قرار می دهد:
فهرست کارها:
GET /api/lists: بازیابی همه فهرست های انجام کار (نمایش خلاصه)
POST /api/lists: یک فهرست کارهای جدید ایجاد کنید
GET /api/lists/{list_id}: یک فهرست کارهای خاص را با تمام موارد آن بازیابی کنید
DELETE /api/lists/{list_id}: حذف یک فهرست کارهای خاص
موارد کار:
POST /api/lists/{list_id}/items: گفت ن یک مورد جدید به یک فهرست خاص
PATCH /api/lists/{list_id}/checked_state: وضعیت علامتدار یک مورد را بهروزرسانی کنید
DELETE /api/lists/{list_id}/items/{item_id}: حذف یک مورد خاص از فهرست
این پروژه یک پایه محکم در توسعه پشته FARM و کانتینریسازی Docker فراهم میکند که میتوانید آن را برای کاربردهای پیچیدهتر در آینده گسترش دهید.
پس بیایید پروژه را شروع کنیم.
آموزش پروژه
راه اندازی پروژه و توسعه Backend
مرحله 1: ساختار پروژه را تنظیم کنید
یک دایرکتوری جدید برای پروژه خود ایجاد کنید:
mkdir farm-stack-todo cd farm-stack-todo
زیر دایرکتوری ها را برای backend و frontend ایجاد کنید:
mkdir backend frontend
مرحله 2: محیط Backend را تنظیم کنید
به دایرکتوری backend بروید:
cd backend
یک محیط مجازی بسازید و آن را فعال کنید:
python -m venv venv source venv/bin/activate # On Windows, use: venv\Scripts\activate
فایل های زیر را در پوشه backend ایجاد کنید:
Dockerfile
pyproject.toml
در ترمینال خود، بسته های مورد نیاز را نصب کنید:
pip install "fastapi[all]" "motor[srv]" beanie aiostream
فایل requirement.txt را ایجاد کنید:
pip freeze > requirements.txt
پس از ایجاد فایل requires.txt (از طریق pip-compile یا دستی)، می توانید وابستگی ها را با استفاده از:
pip install -r requirements.txt
محتوای زیر را به Dockerfile اضافه کنید:
FROM python: 3 WORKDIR /usr/src/app COPY requirements.txt ./ RUN pip install --no-cache-dir --upgrade -r ./requirements.txt EXPOSE 3001 CMD [ "python" , "./src/server.py" ]
محتوای زیر را به pyproject.toml اضافه کنید:
[ tool.pytest.ini_options ] pythonpath = "src"
مرحله 4: ساختار Backend را تنظیم کنید
یک دایرکتوری src در دایرکتوری backend ایجاد کنید:
mkdir src
فایل های زیر را در دایرکتوری src ایجاد کنید:
مرحله 5: پیاده سازی لایه دسترسی به داده (DAL)
src/ dal.py را باز کنید و محتوای زیر را اضافه کنید:
from bson import ObjectId from motor.motor_asyncio import AsyncIOMotorCollection from pymongo import ReturnDocument from pydantic import BaseModel from uuid import uuid4 class ListSummary ( BaseModel ): id: str name: str item_count: int @staticmethod def from_doc ( doc ) -> "ListSummary": return ListSummary( id=str(doc[ "_id" ]), name=doc[ "name" ], item_count=doc[ "item_count" ], ) class ToDoListItem ( BaseModel ): id: str label: str checked: bool @staticmethod def from_doc ( item ) -> "ToDoListItem": return ToDoListItem( id=item[ "id" ], label=item[ "label" ], checked=item[ "checked" ], ) class ToDoList ( BaseModel ): id: str name: str items: list[ToDoListItem] @staticmethod def from_doc ( doc ) -> "ToDoList": return ToDoList( id=str(doc[ "_id" ]), name=doc[ "name" ], items=[ToDoListItem.from_doc(item) for item in doc[ "items" ]], ) class ToDoDAL : def __init__ ( self, todo_collection: AsyncIOMotorCollection ): self._todo_collection = todo_collection async def list_todo_lists ( self, session=None ): async for doc in self._todo_collection.find( {}, projection={ "name" : 1 , "item_count" : { "$size" : "$items" }, }, sort={ "name" : 1 }, session=session, ): yield ListSummary.from_doc(doc) async def create_todo_list ( self, name: str, session=None ) -> str: response = await self._todo_collection.insert_one( { "name" : name, "items" : []}, session=session, ) return str(response.inserted_id) async def get_todo_list ( self, id: str | ObjectId, session=None ) -> ToDoList: doc = await self._todo_collection.find_one( { "_id" : ObjectId(id)}, session=session, ) return ToDoList.from_doc(doc) async def delete_todo_list ( self, id: str | ObjectId, session=None ) -> bool: response = await self._todo_collection.delete_one( { "_id" : ObjectId(id)}, session=session, ) return response.deleted_count == 1 async def create_item ( self, id: str | ObjectId, label: str, session=None, ) -> ToDoList | None : result = await self._todo_collection.find_one_and_update( { "_id" : ObjectId(id)}, { "$push" : { "items" : { "id" : uuid4().hex, "label" : label, "checked" : False , } } }, session=session, return_document=ReturnDocument.AFTER, ) if result: return ToDoList.from_doc(result) async def set_checked_state ( self, doc_id: str | ObjectId, item_id: str, checked_state: bool, session=None, ) -> ToDoList | None : result = await self._todo_collection.find_one_and_update( { "_id" : ObjectId(doc_id), "items.id" : item_id}, { "$set" : { "items.$.checked" : checked_state}}, session=session, return_document=ReturnDocument.AFTER, ) if result: return ToDoList.from_doc(result) async def delete_item ( self, doc_id: str | ObjectId, item_id: str, session=None, ) -> ToDoList | None : result = await self._todo_collection.find_one_and_update( { "_id" : ObjectId(doc_id)}, { "$pull" : { "items" : { "id" : item_id}}}, session=session, return_document=ReturnDocument.AFTER, ) if result: return ToDoList.from_doc(result)
این قسمت 1 آموزش را به پایان می رساند، جایی که ما ساختار پروژه را راه اندازی کردیم و لایه دسترسی به داده را برای برنامه FARM stack todo خود پیاده سازی کردیم. در قسمت بعدی سرور FastAPI را پیاده سازی کرده و نقاط انتهایی API را ایجاد می کنیم.
پیاده سازی سرور FastAPI
مرحله 6: سرور FastAPI را پیاده سازی کنید
src/ server.py را باز کنید و محتوای زیر را اضافه کنید:
from contextlib import asynccontextmanager from datetime import datetime import os import sys from bson import ObjectId from fastapi import FastAPI, status from motor.motor_asyncio import AsyncIOMotorClient from pydantic import BaseModel import uvicorn from dal import ToDoDAL, ListSummary, ToDoList COLLECTION_NAME = "todo_lists" MONGODB_URI = os.environ[ "MONGODB_URI" ] DEBUG = os.environ.get( "DEBUG" , "" ).strip().lower() in { "1" , "true" , "on" , "yes" } @asynccontextmanager async def lifespan ( app: FastAPI ): # Startup: client = AsyncIOMotorClient(MONGODB_URI) database = client.get_default_database() # Ensure the database is available: pong = await database.command( "ping" ) if int(pong[ "ok" ]) != 1 : raise Exception( "Cluster connection is not okay!" ) todo_lists = database.get_collection(COLLECTION_NAME) app.todo_dal = ToDoDAL(todo_lists) # Yield back to FastAPI Application: yield # Shutdown: client.close() app = FastAPI(lifespan=lifespan, debug=DEBUG) @app.get("/api/lists") async def get_all_lists () -> list[ListSummary]: return [i async for i in app.todo_dal.list_todo_lists()] class NewList ( BaseModel ): name: str class NewListResponse ( BaseModel ): id: str name: str @app.post("/api/lists", status_code=status.HTTP_201_CREATED) async def create_todo_list ( new_list: NewList ) -> NewListResponse: return NewListResponse( id= await app.todo_dal.create_todo_list(new_list.name), name=new_list.name, ) @app.get("/api/lists/{list_id}") async def get_list ( list_id: str ) -> ToDoList: """Get a single to-do list""" return await app.todo_dal.get_todo_list(list_id) @app.delete("/api/lists/{list_id}") async def delete_list ( list_id: str ) -> bool: return await app.todo_dal.delete_todo_list(list_id) class NewItem ( BaseModel ): label: str class NewItemResponse ( BaseModel ): id: str label: str @app.post( "/api/lists/{list_id}/items/" , status_code=status.HTTP_201_CREATED, ) async def create_item ( list_id: str, new_item: NewItem ) -> ToDoList: return await app.todo_dal.create_item(list_id, new_item.label) @app.delete("/api/lists/{list_id}/items/{item_id}") async def delete_item ( list_id: str, item_id: str ) -> ToDoList: return await app.todo_dal.delete_item(list_id, item_id) class ToDoItemUpdate ( BaseModel ): item_id: str checked_state: bool @app.patch("/api/lists/{list_id}/checked_state") async def set_checked_state ( list_id: str, update: ToDoItemUpdate ) -> ToDoList: return await app.todo_dal.set_checked_state( list_id, update.item_id, update.checked_state ) class DummyResponse ( BaseModel ): id: str when: datetime @app.get("/api/dummy") async def get_dummy () -> DummyResponse: return DummyResponse( id=str(ObjectId()), when=datetime.now(), ) def main ( argv=sys.argv[ 1 :] ): try : uvicorn.run( "server:app" , host= "0.0.0.0" , port= 3001 , reload=DEBUG) except KeyboardInterrupt: pass if __name__ == "__main__" : main()
این پیادهسازی سرور FastAPI را با میانافزار CORS راهاندازی میکند، به MongoDB متصل میشود و نقاط پایانی API را برای برنامه todo ما تعریف میکند.
مرحله 7: متغیرهای محیط را تنظیم کنید
یک فایل env در دایرکتوری ریشه با محتوای زیر ایجاد کنید. مطمئن شوید که نام پایگاه داده ("todo") را در انتهای ".mongodb.net/" اضافه کنید.
MONGODB_URI= 'mongodb+srv://beau:codecamp@cluster0.ji7hu.mongodb.net/todo?retryWrites=true&w=majority&appName=Cluster0'
مرحله 8: یک فایل docker-compose ایجاد کنید
در دایرکتوری اصلی پروژه خود (farm-stack-todo)، فایلی به نام compose.yml با محتوای زیر ایجاد کنید:
name: todo-app services: nginx: image: nginx: 1.17 volumes: - ./nginx/nginx.conf:/etc/nginx/conf.d/ default .conf ports: - 8000 : 80 depends_on: - backend - frontend frontend: image: "node:22" user: "node" working_dir: /home/node/app environment: - NODE_ENV=development - WDS_SOCKET_PORT= 0 volumes: - ./frontend/:/home/node/app expose: - "3000" ports: - "3000:3000" command: "npm start" backend: image: todo-app/backend build: ./backend volumes: - ./backend/:/usr/src/app expose: - "3001" ports: - "8001:3001" command: "python src/server.py" environment: - DEBUG= true env_file: - path: ./.env required: true
مرحله 9: پیکربندی Nginx را تنظیم کنید
یک دایرکتوری به نام nginx در ریشه پروژه خود ایجاد کنید:
mkdir nginx
یک فایل به نام nginx.conf در دایرکتوری nginx با محتوای زیر ایجاد کنید:
server { listen 80 ; server_name farm_intro; location / { proxy_pass http://frontend: 3000 ; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade" ; } location /api { proxy_pass http://backend: 3001 /api; } }
این پایان بخش 2 آموزش است، جایی که ما سرور FastAPI را پیاده سازی کردیم، متغیرهای محیط را راه اندازی کردیم، یک فایل docker-compose ایجاد کردیم و Nginx را پیکربندی کردیم. در قسمت بعدی، ما بر روی راه اندازی React frontend برای برنامه FARM stack todo تمرکز خواهیم کرد.
راه اندازی React Frontend
مرحله 10: برنامه React را ایجاد کنید
به دایرکتوری frontend بروید:
cd ../frontend
یک برنامه React جدید با استفاده از Create React App ایجاد کنید:
npx create-react-app .
وابستگی های اضافی را نصب کنید:
npm install axios react-icons
مرحله 11: مؤلفه اصلی برنامه را تنظیم کنید
محتوای src/App.js را با موارد زیر جایگزین کنید:
import { useEffect, useState } from "react" ; import axios from "axios" ; import "./App.css" ; import ListToDoLists from "./ListTodoLists" ; import ToDoList from "./ToDoList" ; function App ( ) { const [listSummaries, setListSummaries] = useState( null ); const [selectedItem, setSelectedItem] = useState( null ); useEffect( () => { reloadData().catch( console .error); }, []); async function reloadData ( ) { const response = await axios.get( "/api/lists" ); const data = await response.data; setListSummaries(data); } function handleNewToDoList ( newName ) { const updateData = async () => { const newListData = { name : newName, }; await axios.post( `/api/lists` , newListData); reloadData().catch( console .error); }; updateData(); } function handleDeleteToDoList ( id ) { const updateData = async () => { await axios.delete( `/api/lists/ ${id} ` ); reloadData().catch( console .error); }; updateData(); } function handleSelectList ( id ) { console .log( "Selecting item" , id); setSelectedItem(id); } function backToList ( ) { setSelectedItem( null ); reloadData().catch( console .error); } if (selectedItem === null ) { return ( < div className = "App" > < ListToDoLists listSummaries = {listSummaries} handleSelectList = {handleSelectList} handleNewToDoList = {handleNewToDoList} handleDeleteToDoList = {handleDeleteToDoList} /> </ div > ); } else { return ( < div className = "App" > < ToDoList listId = {selectedItem} handleBackButton = {backToList} /> </ div > ); } } export default App;
مرحله 12: مؤلفه ListTodoLists را ایجاد کنید
یک فایل جدید src/ListTodoLists.js با محتوای زیر ایجاد کنید:
import "./ListTodoLists.css" ; import { useRef } from "react" ; import { BiSolidTrash } from "react-icons/bi" ; function ListToDoLists ( { listSummaries, handleSelectList, handleNewToDoList, handleDeleteToDoList, } ) { const labelRef = useRef(); if (listSummaries === null ) { return < div className = "ListToDoLists loading" > Loading to-do lists ... </ div > ; } else if (listSummaries.length === 0 ) { return ( < div className = "ListToDoLists" > < div className = "box" > < label > New To-Do List: < input id = {labelRef} type = "text" /> </ label > < button onClick = {() => handleNewToDoList(document.getElementById(labelRef).value) } > New </ button > </ div > < p > There are no to-do lists! </ p > </ div > ); } return ( < div className = "ListToDoLists" > < h1 > All To-Do Lists </ h1 > < div className = "box" > < label > New To-Do List: < input id = {labelRef} type = "text" /> </ label > < button onClick = {() => handleNewToDoList(document.getElementById(labelRef).value) } > New </ button > </ div > {listSummaries.map((summary) => { return ( < div key = {summary.id} className = "summary" onClick = {() => handleSelectList(summary.id)} > < span className = "name" > {summary.name} </ span > < span className = "count" > ({summary.item_count} items) </ span > < span className = "flex" > </ span > < span className = "trash" onClick = {(evt) => { evt.stopPropagation(); handleDeleteToDoList(summary.id); }} > < BiSolidTrash /> </ span > </ div > ); })} </ div > ); } export default ListToDoLists;
یک فایل جدید src/ListTodoLists.css با محتوای زیر ایجاد کنید:
.ListToDoLists .summary { border : 1px solid lightgray; padding : 1em ; margin : 1em ; cursor : pointer; display : flex; } .ListToDoLists .count { padding-left : 1ex ; color : blueviolet; font-size : 92% ; }
مرحله 13: مؤلفه ToDoList را ایجاد کنید
یک فایل جدید src/ToDoList.js با محتوای زیر ایجاد کنید:
import "./ToDoList.css" ; import { useEffect, useState, useRef } from "react" ; import axios from "axios" ; import { BiSolidTrash } from "react-icons/bi" ; function ToDoList ( { listId, handleBackButton } ) { let labelRef = useRef(); const [listData, setListData] = useState( null ); useEffect( () => { const fetchData = async () => { const response = await axios.get( `/api/lists/ ${listId} ` ); const newData = await response.data; setListData(newData); }; fetchData(); }, [listId]); function handleCreateItem ( label ) { const updateData = async () => { const response = await axios.post( `/api/lists/ ${listData.id} /items/` , { label : label, }); setListData( await response.data); }; updateData(); } function handleDeleteItem ( id ) { const updateData = async () => { const response = await axios.delete( `/api/lists/ ${listData.id} /items/ ${id} ` ); setListData( await response.data); }; updateData(); } function handleCheckToggle ( itemId, newState ) { const updateData = async () => { const response = await axios.patch( `/api/lists/ ${listData.id} /checked_state` , { item_id : itemId, checked_state : newState, } ); setListData( await response.data); }; updateData(); } if (listData === null ) { return ( < div className = "ToDoList loading" > < button className = "back" onClick = {handleBackButton} > Back </ button > Loading to-do list ... </ div > ); } return ( < div className = "ToDoList" > < button className = "back" onClick = {handleBackButton} > Back </ button > < h1 > List: {listData.name} </ h1 > < div className = "box" > < label > New Item: < input id = {labelRef} type = "text" /> </ label > < button onClick = {() => handleCreateItem(document.getElementById(labelRef).value) } > New </ button > </ div > {listData.items.length > 0 ? ( listData.items.map((item) => { return ( < div key = {item.id} className = {item.checked ? " item checked " : " item "} onClick = {() => handleCheckToggle(item.id, !item.checked)} > < span > {item.checked ? "✅" : "⬜️"} </ span > < span className = "label" > {item.label} </ span > < span className = "flex" > </ span > < span className = "trash" onClick = {(evt) => { evt.stopPropagation(); handleDeleteItem(item.id); }} > < BiSolidTrash /> </ span > </ div > ); }) ) : ( < div className = "box" > There are currently no items. </ div > )} </ div > ); } export default ToDoList;
یک فایل جدید src/ToDoList.css با محتوای زیر ایجاد کنید:
.ToDoList .back { margin : 0 1em ; padding : 1em ; float : left; } .ToDoList .item { border : 1px solid lightgray; padding : 1em ; margin : 1em ; cursor : pointer; display : flex; } .ToDoList .label { margin-left : 1ex ; } .ToDoList .checked .label { text-decoration : line-through; color : lightgray; }
مرحله 14: فایل CSS اصلی را به روز کنید
محتوای src/index.css را با موارد زیر جایگزین کنید:
html , body { margin : 0 ; font-family : -apple-system, BlinkMacSystemFont, 'Segoe UI' , 'Roboto' , 'Oxygen' , 'Ubuntu' , 'Cantarell' , 'Fira Sans' , 'Droid Sans' , 'Helvetica Neue' , sans-serif; -webkit-font-smoothing : antialiased; -moz-osx-font-smoothing : grayscale; font-size : 12pt ; } input , button { font-size : 1em ; } code { font-family : source-code-pro, Menlo, Monaco, Consolas, 'Courier New' , monospace; } .box { border : 1px solid lightgray; padding : 1em ; margin : 1em ; } .flex { flex : 1 ; }
این قسمت 3 آموزش را به پایان می رساند، جایی که ما بخش React را برای برنامه FARM stack todo خود راه اندازی کردیم. ما مؤلفه اصلی App، مؤلفه ListTodoLists را برای نمایش همه فهرستهای کار، و مؤلفه ToDoList را برای فهرستهای تک تک کار ایجاد کردهایم. در قسمت بعدی بر روی اجرا و تست اپلیکیشن تمرکز خواهیم کرد.
اجرای و تست برنامه
مرحله 18: برنامه را با استفاده از Docker Compose اجرا کنید
مطمئن شوید که Docker و Docker Compose را روی سیستم خود نصب کرده اید
یک ترمینال را در فهرست اصلی پروژه خود باز کنید (farm-stack-todo)
کانتینرها را بسازید و راه اندازی کنید:
docker-compose up --build
پس از آماده شدن کانتینرها، مرورگر وب خود را باز کنید و به http://localhost:8000 بروید
مرحله 19: توقف برنامه
اگر برنامه را بدون Docker اجرا می کنید:
سرور توسعه React را با فشار دادن Ctrl+C در ترمینال آن متوقف کنید
سرور FastAPI را با فشار دادن Ctrl+C در ترمینال آن متوقف کنید
سرور MongoDB را با فشار دادن Ctrl+C در ترمینال آن متوقف کنید
اگر برنامه را با Docker Compose اجرا می کنید:
Ctrl+C را در ترمینالی که docker-compose up را اجرا کردید فشار دهید
دستور زیر را برای توقف و حذف کانتینرها اجرا کنید:
docker-compose down
```
تبریک می گویم! شما یک برنامه کاربردی FARM stack todo را با موفقیت ساخته و آزمایش کرده اید. این برنامه ادغام FastAPI، React و MongoDB را در یک برنامه وب تمام پشته نشان می دهد.
در اینجا برخی از مراحل بعدی بالقوه برای بهبود برنامه شما آورده شده است:
احراز هویت و مجوز کاربر را اضافه کنید
اعتبار سنجی داده ها و مدیریت خطا را پیاده سازی کنید
آپشن های بیشتری مانند تاریخهای سررسید، اولویتها یا دستهها را برای موارد انجام کار اضافه کنید
UI/UX را با طراحی زیباتر بهبود دهید
تست های واحد و ادغام را برای هر دو قسمت جلویی و باطنی بنویسید
یکپارچه سازی و استقرار مداوم (CI/CD) را برای برنامه خود تنظیم کنید
به یاد داشته باشید که وابستگی های خود را به روز نگه دارید و بهترین شیوه ها را برای امنیت و عملکرد در حین توسعه برنامه خود دنبال کنید.
نتیجه گیری و مراحل بعدی
بابت تکمیل این آموزش جامع FARM stack تبریک می گویم! با ساخت این اپلیکیشن todo، تجربه عملی با برخی از قدرتمندترین و محبوب ترین فناوری ها در توسعه وب مدرن به دست آورده اید. شما یاد گرفته اید که چگونه با FastAPI یک Backend API قوی ایجاد کنید، یک frontend پویا و پاسخگو با React بسازید، داده ها را با MongoDB حفظ کنید، و کل برنامه خود را با استفاده از Docker کانتینری کنید. این پروژه نشان داده است که چگونه این فناوری ها به طور یکپارچه با هم کار می کنند تا یک برنامه وب با امکانات کامل و مقیاس پذیر ایجاد کنند.
ارسال نظر