Jannah Theme License is not validated, Go to the theme options page to validate the license, You need a single license for each domain name.
تقنية وتكنولوجيا

تعبئة عميل TypeScript الخاص بك في واجهة Python الخلفية | بواسطة إيتاي بيتان


تصوير ماركوس سباسك على Unsplash

دليل عملي كامل

قم بدمج تطبيق React الخاص بك مع خادم الويب FastAPI

ستتعلم في هذا الدليل كيفية تجميع تطبيق TypeScript React بسيط في ملف حزمة بايثون وخدمته من خادم الويب FastAPI Python الخاص بك. تحقق من مستودعات العميل والخادم، إذا كنت تريد رؤية الكود الكامل. هيا بنا نبدأ!

أثناء عملية التطوير، من المحتمل أنك تستخدم معرفين مختلفين:

  1. نافذة TypeScript أو JavaScript React App، تعمل على منفذ استماع مخصص (على سبيل المثال، 5173) لخدمة صفحات العميل/الواجهة الأمامية.
  2. 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 Path

cwd = 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 run

def 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, status

STATUS = 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).

تشغيل خادم Python مع تطبيق React (الصورة من تأليف المؤلف)

في هذا البرنامج التعليمي، أنشأنا تطبيق React بسيطًا يقوم باستدعاء واحد للواجهة الخلفية. لقد قمنا بتغليف تطبيق العميل هذا كحزمة Python وتقديمه من خادم الويب FastAPI Python الخاص بنا.

يتيح لك استخدام هذا الأسلوب الاستفادة من أفضل الأدوات في كلا العالمين: TypeScript وReact للواجهة الأمامية، وPython مع FastAPI للواجهة الخلفية. ومع ذلك، فإننا نريد الحفاظ على التماسك العالي والاقتران المنخفض بين هذين المكونين. وبهذه الطريقة، سوف تحصل على جميع الفوائد:

  • السرعة، من خلال فصل الواجهة الأمامية والخلفية إلى مستودعات مختلفة، يمكن تطوير كل جزء بواسطة فريق مختلف.
  • الاستقرار والجودة، عن طريق قفل حزمة العميل التي تم إصدارها وإيقافها فقط عندما يكون الخادم جاهزًا لدعم إصدار العميل الجديد.
  • الأمان – يتفاعل المتصفح مع خادم خلفي واحد فقط. لا نحتاج إلى تمكين CORS أو أي حلول أخرى تهدد الأمان.
  • البساطة – من خلال العمل عبر خادم واحد

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

زر الذهاب إلى الأعلى