Python - Vite

Integration of a Python server and a Typescript client using Vite and a development proxy.

Introduction

We will create a web application in which:

  • The server is written with FastAPI
  • The client is written in React

The client and server communicate using JSON.

Server PythonClient TypescriptInternet

Working environment

Clone the project:

Terminal window
$ git clone https://gitlab.com/xtec/python/vite

Server

The backend server is developed completely independently of the frontend.

Start the Python server through the Deno task:

Terminal window
$ deno task server

The server exposes an HTTP endpoint at:

Note

All API endpoints must start with /api/

Client

Now start the Typescript - Vite development server:

Terminal window
$ deno task client

Have a look at the file vite.config.ts:

// ...
export default defineConfig({
// ...
server: {
port: 3000,
cors: true,
proxy: {
'/api': {
target: 'http://localhost:8000',
}
},
})

The Vite dev server runs on http://127.0.0.1:3000 and is configured to proxy API requests to the backend server on http://127.0.0.1:8000.

This is done using the server.proxy option. All HTTP requests whose path starts with /api are forwarded transparently to http://localhost:8000.

If you open:

you will see the same response as the backend endpoint:

From the React application’s point of view, this proxy is completely transparent. In App.tsx you can see a data fetch like this:

const { data, error } = useSWR("/api/time", fetcher)

Notice that:

  • You do not specify localhost.
  • You do not specify any port.
  • You only use the path (/api/time).

Production

In production, the backend server must serve both:

  • All API endpoints.
  • All static client assets (the built React application).

First, build the client application with Vite - Build:

Terminal window
$ deno task build

This creates a directory with all the static assets for the client, typically placed under server/static (depending on the project configuration).

The server is configured to serve static files from this directory if it exists, for example:

You can see that a server/static directory has been created with all the static content of the client.

The server is configured to serve the static files from this directory if it exists:

if os.path.exists("static"):
app.mount("/", StaticFiles(directory="static", html=True), name="static")
Note

This code must be added at the end of the route configuration so that the / rule is applied last, after the API routes.

Restart the server and go to:

You should now see the client application being served directly by the backend server. The same origin (http://127.0.0.1:8000) is used for both the API (/api/...) and the frontend (static files).

Docker

Finally, package the application into a container image and push it to Docker Hub.

Terminal window
docker build --tag vite .
docker run --rm -p 80:8000 vite

You can follow these two help documents: