راهنمای عملی کامل
برنامه React خود را با وب سرور FastAPI ترکیب کنید
در این راهنما، یاد خواهید گرفت که چگونه یک برنامه ساده TypeScript React را در یک بسته بندی کنید بسته پایتون و آن را از سرور وب FastAPI Python خود سرو کنید. اگر می خواهید کد کامل را ببینید، مخازن مشتری و سرور را بررسی کنید. بیا شروع کنیم!
در طول فرآیند توسعه، شما احتمالا از دو IDE مختلف استفاده می کنید:
- یک پنجره TypeScript یا JavaScript React App که بر روی یک پورت گوش دادن اختصاصی (مثلاً 5173) اجرا می شود تا به صفحات کلاینت/فرانت پایانی ارائه شود.
- Python FastAPI در حال اجرا بر روی یک پورت دیگر (مثلا 8080) برای سرویس REST API.
به عبارت دیگر، شما دو سرور مختلف دارید که به صورت محلی اجرا می شوند. هر بار که می خواهید با سرور FastAPI خود تماس بگیرید، مرورگر با دو سرور مختلف تعامل دارد.
در حالی که به صورت محلی خوب کار می کند (ج localhost
)، هنگام استقرار این کد با خطای “Cross-Origin Request Blocked” در مرورگر خود مواجه خواهید شد. قبل از اینکه کد خود را به تولید برسانید، بهترین کار این است که هم صفحات سرویس گیرنده و هم REST API را از یک سرور وب پشتیبان ارائه دهید. به این ترتیب مرورگر با یک Backend تعامل خواهد داشت. برای امنیت، عملکرد و سادگی بهتر است.
1. یک برنامه Simple React ایجاد کنید
اول، در مال شما workspace
دایرکتوری، بیایید یک برنامه TypeScript React جدید با استفاده از vite ایجاد کنیم:
~/workspace ➜ npm create vite@latest
✔ Project name: … vite-project
✔ Select a framework: › React
✔ Select a variant: › TypeScript
سپس وارد دایرکتوری پروژه جدید شوید، وابستگی ها را نصب کنید و برنامه را اجرا کنید (http://localhost:5173):
~/workspace ➜ cd vite-project
~/workspace/vite-project ➜ npm install
~/workspace/vite-project ➜ npm run dev
شما باید چیزی شبیه به:
اکنون بیایید یک افزودنی کوچک به الگو ایجاد کنیم – یک تماس HTTP ناهمزمان به باطن FastAPI آینده اضافه می کنیم تا وضعیت آن را دریافت کنیم:
function App() {
...
const [health, setHealth] = useState('');useEffect(() => {
const getStatus = async () => {
const response = await fetch('/v1/health-check/liveness', {
method: 'GET',
});
let status: { [status: string]: string } = {};
try {
status = await response.json();
} catch (err) {
console.log(`failed to get backend status. ${err}`);
}
setHealth(status['status'] || 'unknown');
};
getStatus();
}, []);
return (
...
<div>Backend Status: {health}</div>
...
)
}
و اکنون باید چیزی شبیه به این دریافت کنیم:
در این لحظه، وضعیت Backend است unknown
چون هنوز آن را اجرا نکرده ایم. نگران نباش به زودی بهش میرسیم در نهایت، اجازه دهید مشتری را برای بسته بندی بعدا بسازیم:
~/workspace/vite-project ➜ npm run build
خروجی کامپایل باید a ایجاد کند dist
پوشه ای با کد بهینه سازی نهایی که به شکل زیر است:
└── dist/
├── assets/
├── static/
└── index.html
2. ساخت بسته پایتون
در این مرحله به پایتون سوئیچ می کنیم. ترجیح می دهم در محیط مجازی برای انزوا کار کنم. ما در یک محیط مجازی اختصاصی نصب خواهیم کرد twine
و build
برای ایجاد بسته پایتون:
~/workspace/vite-project ➜ python3 -m venv venv
~/workspace/vite-project ➜ . venv/bin/activate
~/workspace/vite-project (venv) ➜ python -m pip install --upgrade pip
~/workspace/vite-project (venv) ➜ pip install twine==5.0.0 build==1.2.1
بیایید یک مورد جدید ایجاد کنیم setup.py
فایل در پوشه ریشه (vite-project
، با محتوای زیر:
from setuptools import setup
from pathlib import Pathcwd = Path(__file__).parent
long_description = (cwd / "README.md").read_text()
setup(
name="vite-project",
version="0.0.1",
package_dir={"vite_project": "dist"},
package_data={"vite_project": ["**/*.*"]},
long_description=long_description,
long_description_content_type="text/markdown",
)
و برای ایجاد پکیج موارد زیر را اجرا کنید:
~/workspace/vite-project (venv) ➜ python setup.py sdist -d tmp
~/workspace/vite-project (venv) ➜ python -m build --wheel --outdir tmp
~/workspace/vite-project (venv) ➜ twine upload -u ${USERNAME} -p ${PASSWORD} --repository-url ${REPO_URL} tmp/*
اگر قصد دارید بسته خود را در یک مخزن راه دور مانند PyPI، JFrog Artifactory و غیره آپلود کنید، خط آخر بالا اختیاری است.
3. یک وب سرور FastAPI Python ایجاد کنید
مرحله آخر ساخت سرور پایتون و استفاده از بسته مشتری است. برای این منظور ما:
- یک مورد جدید ایجاد کنید
backend
اشاره گر - یک محیط مجازی جدید ایجاد کنید.
- بسته های مربوطه و بسته مشتری ما را نصب کنید:
~/workspace/backend ➜ python3 -m venv venv
~/workspace/backend ➜ . venv/bin/activate
~/workspace/backend (venv) ➜ python -m pip install --upgrade pip
~/workspace/backend (venv) ➜ pip install fastapi==0.110.0 uvicorn==0.29.0
~/workspace/backend (venv) ➜ pip install ~/workspace/vite-project/tmp/vite-project-0.0.1.tar.gz
توجه داشته باشید که بسته مشتری خود را از مسیر محلی که قبلا ایجاد کرده بودیم نصب کردیم. اگر بسته خود را در یک مخزن راه دور آپلود کرده اید، می توانید آن را با استفاده از:
~/workspace/backend (venv) ➜ pip install --extra-index-url https://${USERNAME}:${PASSWORD}@${REPO_URL} vite-project==0.0.1
بعد، بیایید یک سرور ساده پایتون (2 فایل) ایجاد کنیم:
__main__.py
from distutils.sysconfig import get_python_lib
from fastapi import FastAPI
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
from backend.health_router import router
from uvicorn import rundef create_app():
app = FastAPI(
title="Backend Server",
)
app.include_router(router)
client_path = f"{get_python_lib()}/vite_project"
app.mount("/assets", StaticFiles(directory=f"{client_path}/assets"), name="assets")
app.mount("/static", StaticFiles(directory=f"{client_path}/static"), name="static")
@app.get("/{catchall:path}")
async def serve_react_app(catchall: str):
return FileResponse(f"{client_path}/index.html")
return app
def main():
app = create_app()
run(app, host="0.0.0.0", port=8080)
if __name__ == "__main__":
main()
health_router.py
from typing import Literal
from typing_extensions import TypedDict
from fastapi import APIRouter, statusSTATUS = Literal["success", "error", "partial", "unknown"]
class ReturnHealthcheckStruct(TypedDict):
status: STATUS
router = APIRouter(
prefix="/v1/health-check",
tags=["Health Check"],
)
@router.get(
"/liveness",
summary="Perform a Liveness Health Check",
response_description="Return HTTP Status Code 200 (OK)",
status_code=status.HTTP_200_OK,
response_model=ReturnHealthcheckStruct,
)
async def liveness() -> ReturnHealthcheckStruct:
return {"status": "success"}
در پیادهسازی بالا، با نصب کردن، پشتیبانی را برای ارائه هر فایل استاتیک از برنامه مشتری خود اضافه کردیم static
و assets
پوشه ها و همچنین هر فایل مشتری دیگری که توسط سرور پایتون ما ارائه می شود.
ما همچنین یک نقطه پایانی ساده GET ایجاد کردیم، v1/health-check/liveness
که ساده برمیگرده {“status": “success"}
پاسخ JSON به این ترتیب میتوانیم اطمینان حاصل کنیم که سرور ما هم فایلهای مشتری ثابت و هم API RESTful سمت سرور را مدیریت میکند.
حالا اگر به localhost:8080 برویم، میتوانیم مشتری خود را در حال اجرا ببینیم. توجه کن به وضعیت Backend در زیر، در حال حاضر آن است success
(نسبت به. تا unknown
).
در این آموزش، ما یک برنامه ساده React ایجاد کردیم که یک تماس واحد را با backend برقرار می کند. ما این برنامه مشتری را به عنوان یک بسته Python بسته بندی کردیم و آن را از وب سرور Python FastAPI خود ارائه کردیم.
استفاده از این رویکرد به شما امکان میدهد از بهترینهای هر دو جهان استفاده کنید: TypeScript و React برای فرانتاند و Python با FastAPI برای Backend. با این حال، ما می خواهیم انسجام بالا و اتصال آزاد بین این دو جزء را حفظ کنیم. به این ترتیب شما از تمام مزایای زیر برخوردار خواهید شد:
- سرعت، با تقسیم قسمت جلویی و انتهایی به مخازن مختلف، هر قسمت می تواند توسط تیم متفاوتی توسعه یابد.
- پایداری و کیفیت، با قفل کردن بسته کلاینت نسخه شده و ضربه زدن به آن تنها زمانی که سرور آماده پشتیبانی از نسخه مشتری جدید است.
- امنیت – مرورگر تنها با یک سرور پشتیبان تعامل دارد. ما نیازی به فعال کردن CORS یا سایر راهحلهای مخل امنیت نداریم.
- سادگی – با کار از طریق یک سرور واحد