تعبئة عميل TypeScript الخاص بك في واجهة Python الخلفية | بواسطة إيتاي بيتان
دليل عملي كامل
قم بدمج تطبيق React الخاص بك مع خادم الويب FastAPI
ستتعلم في هذا الدليل كيفية تجميع تطبيق TypeScript React بسيط في ملف حزمة بايثون وخدمته من خادم الويب FastAPI Python الخاص بك. تحقق من مستودعات العميل والخادم، إذا كنت تريد رؤية الكود الكامل. هيا بنا نبدأ!
أثناء عملية التطوير، من المحتمل أنك تستخدم معرفين مختلفين:
- نافذة TypeScript أو JavaScript React App، تعمل على منفذ استماع مخصص (على سبيل المثال، 5173) لخدمة صفحات العميل/الواجهة الأمامية.
- Python FastAPI، يعمل على منفذ مختلف (على سبيل المثال، 8080) لخدمة REST API.
بمعنى آخر، لديك خادمان مختلفان يعملان محليًا. عندما تريد الاتصال بخادم FastAPI الخاص بك، يتفاعل المتصفح مع خادمين مختلفين.
بينما يعمل بشكل جيد محليًا (في localhost
)، فسوف تواجه خطأ “تم حظر الطلب عبر الأصل” في متصفحك عند نشر هذا الرمز. قبل نقل التعليمات البرمجية الخاصة بك إلى الإنتاج، فإن أفضل الممارسات هي خدمة كل من صفحات العميل وREST API من نفس خادم الويب الخلفي. بهذه الطريقة سيتفاعل المتصفح مع واجهة خلفية واحدة. إنه أفضل للأمان والأداء والبساطة.
1. قم بإنشاء تطبيق 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>
...
)
}
والآن يجب أن نحصل على شيء مثل هذا:
عند هذه النقطة، حالة الخلفية يكون unknown
لأننا لم ننفذه بعد. لا تقلق، سوف نتعامل مع هذا قريبا. وأخيرًا، لنقم ببناء العميل لتعبئته لاحقًا:
~/workspace/vite-project ➜ npm run build
يجب أن ينشئ إخراج البناء ملف 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
بعد ذلك، لنقم بإنشاء خادم Python بسيط (ملفين):
__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
المجلدات، بالإضافة إلى أي ملف عميل آخر يتم تقديمه بواسطة خادم Python الخاص بنا.
لقد أنشأنا أيضًا نقطة نهاية GET بسيطة، v1/health-check/liveness
التي ترجع بسيطة {“status": “success"}
استجابة جيسون. وبهذه الطريقة يمكننا التأكد من أن خادمنا يتعامل مع كل من ملفات العميل الثابتة وواجهة برمجة تطبيقات RESTful من جانب الخادم.
الآن، إذا انتقلنا إلى localhost:8080 يمكننا رؤية عميلنا قيد التشغيل. انتبه إلى حالة الخلفية أدناه، هو الآن success
(بدلا من unknown
).
في هذا البرنامج التعليمي، أنشأنا تطبيق React بسيطًا يقوم باستدعاء واحد للواجهة الخلفية. لقد قمنا بتغليف تطبيق العميل هذا كحزمة Python وتقديمه من خادم الويب FastAPI Python الخاص بنا.
يتيح لك استخدام هذا الأسلوب الاستفادة من أفضل الأدوات في كلا العالمين: TypeScript وReact للواجهة الأمامية، وPython مع FastAPI للواجهة الخلفية. ومع ذلك، فإننا نريد الحفاظ على التماسك العالي والاقتران المنخفض بين هذين المكونين. وبهذه الطريقة، سوف تحصل على جميع الفوائد:
- السرعة، من خلال فصل الواجهة الأمامية والخلفية إلى مستودعات مختلفة، يمكن تطوير كل جزء بواسطة فريق مختلف.
- الاستقرار والجودة، عن طريق قفل حزمة العميل التي تم إصدارها وإيقافها فقط عندما يكون الخادم جاهزًا لدعم إصدار العميل الجديد.
- الأمان – يتفاعل المتصفح مع خادم خلفي واحد فقط. لا نحتاج إلى تمكين CORS أو أي حلول أخرى تهدد الأمان.
- البساطة – من خلال العمل عبر خادم واحد
اكتشاف المزيد من موقع علم
اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.