Home Machine Learning Packaging Your TypeScript Shopper right into a Python Backend | by Itay Bittan | Apr, 2024

Packaging Your TypeScript Shopper right into a Python Backend | by Itay Bittan | Apr, 2024

0
Packaging Your TypeScript Shopper right into a Python Backend | by Itay Bittan | Apr, 2024

[ad_1]

Photograph by Markus Spiske on Unsplash

A FULL HANDS-ON GUIDE

Mix your React Software with the FastAPI web-server

On this information, you’ll discover ways to bundle a easy TypeScript React Software right into a Python bundle and serve it out of your FastAPI Python internet server. Take a look at the shopper and the server repos, if you wish to see the total code. Let’s get began!

Through the improvement course of, you most likely use two completely different IDEs:

  1. TypeScript or JavaScript React App window, operating on a devoted listening port (e.g., 5173) to serve the shopper/frontend pages.
  2. Python FastAPI, operating on a distinct port (e.g., 8080) to serve a REST API.

In different phrases, you may have two completely different servers operating domestically. Everytime you need to name your FastAPI server, the browser interacts with two completely different servers.

Native improvement (Picture by Creator)

Whereas it really works high-quality domestically (in localhost), you’ll encounter a “Cross-Origin Request Blocked” error in your browser while you deploy that code. Earlier than taking your code to manufacturing, the most effective follow is to serve each shopper pages and REST API from the identical backend internet server. That method the browser will work together with a single backend. It’s higher for safety, efficiency, and ease.

Getting ready for Manufacturing (Picture by Creator)

1. Create a Easy React Software

First, in your workspace listing, let’s create a brand new TypeScript React software utilizing vite:

~/workspace ➜ npm create vite@newest
✔ Challenge identify: … vite-project
✔ Choose a framework: › React
✔ Choose a variant: › TypeScript

Then, enter into the brand new challenge listing, set up the dependencies, and run the applying (http://localhost:5173):

~/workspace ➜ cd vite-project
~/workspace/vite-project ➜ npm set up
~/workspace/vite-project ➜ npm run dev

You need to see one thing like:

First Vite React Template (Picture by Creator)

Now, let’s make a small addition to the template — we’ll add an async HTTP name to the longer term FastAPI backend to get its standing:

perform App() {
...
const [health, setHealth] = useState('');

useEffect(() => {
const getStatus = async () => {
const response = await fetch('/v1/health-check/liveness', {
methodology: 'GET',
});
let standing: { [status: string]: string } = {};
attempt {
standing = await response.json();
} catch (err) {
console.log(`didn't get backend standing. ${err}`);
}
setHealth(standing['status'] || 'unknown');
};
getStatus();
}, []);

return (
...
<div>Backend Standing: {well being}</div>
...
)
}

And now we must always get one thing like this:

With a Backend name (Picture by Creator)

At this level, the Backend Standing is unknown as a result of we haven’t carried out it but. No worries, we are going to deal with that shortly. Lastly, let’s construct the shopper for packaging it in a while:

~/workspace/vite-project ➜ npm run construct

The construct output ought to create a dist folder with the ultimate optimized code that appears like this:

└── dist/
├── belongings/
├── static/
└── index.html

2. Constructing a Python Package deal

At this level, we’re switching to Python. I favor to work in a digital surroundings for isolation. In a devoted digital surroundings, we are going to set up twine and construct , for creating our Python bundle:

~/workspace/vite-project ➜ python3 -m venv venv
~/workspace/vite-project ➜ . venv/bin/activate
~/workspace/vite-project (venv) ➜ python -m pip set up --upgrade pip
~/workspace/vite-project (venv) ➜ pip set up twine==5.0.0 construct==1.2.1

Let’s create a brand new setup.py file within the root folder (vite-project), with the next content material:

from setuptools import setup
from pathlib import Path

cwd = Path(__file__).dad or mum
long_description = (cwd / "README.md").read_text()

setup(
identify="vite-project",
model="0.0.1",
package_dir={"vite_project": "dist"},
package_data={"vite_project": ["**/*.*"]},
long_description=long_description,
long_description_content_type="textual content/markdown",
)

and run the next to create the bundle:

~/workspace/vite-project (venv) ➜ python setup.py sdist -d tmp
~/workspace/vite-project (venv) ➜ python -m construct --wheel --outdir tmp
~/workspace/vite-project (venv) ➜ twine add -u ${USERNAME} -p ${PASSWORD} --repository-url ${REPO_URL} tmp/*

The final line above is non-obligatory in case you intend to add your bundle to a distant repository similar to PyPI, JFrog Artifactory, and so forth.

3. Create a FastAPI Python web-server

The ultimate step is to construct the Python server and use the shopper bundle. For that, we are going to:

  • Create a brand new backendlisting.
  • Create a brand new digital surroundings.
  • Set up the related packages and our shopper bundle:
~/workspace/backend ➜ python3 -m venv venv
~/workspace/backend ➜ . venv/bin/activate
~/workspace/backend (venv) ➜ python -m pip set up --upgrade pip
~/workspace/backend (venv) ➜ pip set up fastapi==0.110.0 uvicorn==0.29.0
~/workspace/backend (venv) ➜ pip set up ~/workspace/vite-project/tmp/vite-project-0.0.1.tar.gz

Word that we put in our shopper bundle from a neighborhood path that we created earlier. When you uploaded your bundle to a distant repository, you possibly can set up it with:

~/workspace/backend (venv) ➜ pip set up --extra-index-url https://${USERNAME}:${PASSWORD}@${REPO_URL} vite-project==0.0.1

Subsequent, let’s create a easy Python server (2 information):

__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("/belongings", StaticFiles(listing=f"{client_path}/belongings"), identify="belongings")
app.mount("/static", StaticFiles(listing=f"{client_path}/static"), identify="static")

@app.get("/{catchall:path}")
async def serve_react_app(catchall: str):
return FileResponse(f"{client_path}/index.html")

return app

def important():
app = create_app()
run(app, host="0.0.0.0", port=8080)

if __name__ == "__main__":
important()

health_router.py

from typing import Literal
from typing_extensions import TypedDict
from fastapi import APIRouter, standing

STATUS = Literal["success", "error", "partial", "unknown"]

class ReturnHealthcheckStruct(TypedDict):
standing: STATUS

router = APIRouter(
prefix="/v1/health-check",
tags=["Health Check"],
)

@router.get(
"/liveness",
abstract="Carry out a Liveness Well being Examine",
response_description="Return HTTP Standing Code 200 (OK)",
status_code=standing.HTTP_200_OK,
response_model=ReturnHealthcheckStruct,
)
async def liveness() -> ReturnHealthcheckStruct:
return {"standing": "success"}

Within the implementation above, we added help for serving any static file from our shopper software by mounting the static and belongings folders, in addition to every other shopper file to be served by our Python server.

We additionally created a easy GET endpoint, v1/health-check/liveness that returns a easy {“standing": “success"} JSON response. That method we will be sure that our server handles each shopper static information and our server-side RESTful API.

Now, if we go to localhost:8080 we will see our shopper up and operating. Take note of the Backend Standing beneath, it’s now success (slightly than unknown).

Operating a Python server along with React Software (Picture by Creator)

On this tutorial, we created a easy React Software that does a single name to the backend. We wrapped this shopper software as a Python bundle and served it from our FastAPI Python internet server.

Utilizing this method lets you leverage the most effective instruments in each worlds: TypeScript and React for the frontend, and Python with FastAPI for the backend. But, we need to hold excessive cohesion and low coupling between these two parts. That method, you’ll get all the advantages:

  • Velocity, by separating front-end and backend to completely different repositories, every half might be developed by a distinct staff.
  • Stability and High quality, by locking a versioned shopper bundle and bumping it solely when the server is able to help a brand new shopper model.
  • Security — The browser interacts with just one backend server. We don’t have to allow CORS or every other security-compromising workarounds.
  • Simplicity — By working through a single server

[ad_2]