Skip to content

Instantly share code, notes, and snippets.

@8area8
Last active February 17, 2022 23:42
Show Gist options
  • Save 8area8/cb5ba31df06ea962cbfcf4dcb50a2d46 to your computer and use it in GitHub Desktop.
Save 8area8/cb5ba31df06ea962cbfcf4dcb50a2d46 to your computer and use it in GitHub Desktop.
VueCLI + FastAPI

VueCLI + FastAPI

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.

Base Skeleton

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

The Dockerfiles

FastAPI

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/*

Vue CLI

FROM node

RUN mkdir /code
WORKDIR /code

COPY package.json yarn.lock /code/
RUN yarn install
RUN yarn global add @vue/cli

COPY . /code

Docker-compose

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"

Configure Vue CLI

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

Configure FastAPI

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.

FAQ

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment