This Gist allows to run VueCLI in FastAPI.
- In dev, you will have to launch both servers and use fastAPI for navigation.
- In prod, it will be enough to build VueCLI, and you will have to launch FastAPI only.
back
server.py
front
package.json
Dockerfile # front dockerfile
... # all vue cli stuff
Dockerfile # back dockerfile
.dockerignore
pyproject.toml
poetry.lock
README.md
I personally develop entirely in containers (thanks to the VSCode remote ssh extension). It sometimes requires to modify the docker images on time to generate the basic files for development (the pyproject.toml, or the package.json for example).
You'll need to install fastAPI
on the Python side (at the root) with uvicorn
,
and vue cli 5
on the nodejs side (in front folder), with typescript and router extensions. The complete vuecli environment should fit in the front
folder (avoid making a sub-folder, otherwise it won't work).
FROM python:3.10
RUN pip3 install poetry
ENV POETRY_VIRTUALENVS_CREATE=false
RUN mkdir /code
WORKDIR /code
COPY pyproject.toml poetry.lock /code/
RUN poetry install --no-interaction --no-ansi
COPY . /code
.dockerignore
:
!*/front/dist/*
*/front/*
FROM node
RUN mkdir /code
WORKDIR /code
COPY package.json yarn.lock /code/
RUN yarn install
RUN yarn global add @vue/cli
COPY . /code
version: "3.1"
services:
web:
build: .
command: uvicorn back.server:app --host='0.0.0.0' --debug --reload
container_name: plenkton-app
volumes:
- .:/code
ports:
- "8000:8000"
vue:
build:
context: ./front/
command: yarn serve --host 0.0.0.0 --port 3000
container_name: vuecli-app
volumes:
- ./front:/code
ports:
- "3000:3000"
vue.config.ts
:
const { defineConfig } = require("@vue/cli-service");
module.exports = defineConfig({
transpileDependencies: true,
publicPath: "/static/",
configureWebpack: {
devServer: {
devMiddleware: {
index: true,
mimeTypes: { phtml: "text/html" },
publicPath: "./dist",
serverSideRender: true,
writeToDisk: true,
},
},
},
});
router/index.js
// ...
const router = createRouter({
history: createWebHistory("/"), // Be sure the base url is "/"
routes
})
// ...
- we make sure to write the files in dist in dev mode (to access them from our server)
- We prefix all our files with static, to allow our server to manage them as static files
server.py
:
"""Base server."""
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from starlette.responses import FileResponse
app = FastAPI()
app.mount("/static", StaticFiles(directory="front/dist"), name="static")
@app.get("/{file_path:path}")
async def root():
return FileResponse("front/dist/index.html")
The idea here is clear:
- get the html file generated by Vue CLI
- Enable the display of statics via a static file server, starting with /static/
Since we use the history mode in Vue CLI, we need to redirect all URLs to index.html
. That's why we get any kind of path in the url.
We use the prefix /static/ to distinguish url paths from static files.
why is the Dockerfile backend at the root?
- This is the only Dockerfile that is useful in production. The fastAPI dockerfile is the main one. It is also necessary to access the frontend folder, to link the static files to the server. This would be impossible by putting the dockerfile in the
back
folder.