Search code examples
buildstaticvuejs3fastapivite

fastapi static files with vite build (vue3)


I am currently migrating from my vue2 application (created using vue cli service) to vue3 (using vite). I have a backend written in fastapi, which serves as backend and provides the static frontend files aswell.

This is my main.py, when I use it this way, it works fine with the old application (vue cli)

app.mount("/static", StaticFiles(directory="static"), name="static")


@app.get("/{full_path:path}")
def show_test():
    return FileResponse("static/index.html", media_type="text/html")

My vue.config.js had this, to make it work properly:

module.exports = {
  publicPath: "/static/",
};

So the publicPath was necessary to make it work in vue2 using vue cli.

But now I created the app using vite and there is no "publicPath" anymore but a "base" attribute for the vite.config.js

export default defineConfig({
...
  base: '/static/',
})

With this config if works, but now I am getting "static" in the url for each path, like localhost:8000/static/login and when I refresh the page it causes an error, because it does not recognize the url.

With the vue2 application and the publicPath it worked fine and only showed localhost:8000/login, and refreshes worked fine aswell.

So what need to be changed in the fastapi api.py or in the vite.config.ts to make this work?

Thank you


Solution

  • Ok I managed to get it to work using a npm plugin: https://www.npmjs.com/package/vite-plugin-dynamic-base

    so this is my vite.config.ts:

    import { fileURLToPath, URL } from 'node:url'
    
    import { defineConfig } from 'vite'
    import { dynamicBase } from 'vite-plugin-dynamic-base'
    
    import vue from '@vitejs/plugin-vue'
    import vueJsx from '@vitejs/plugin-vue-jsx'
    
    // https://vitejs.dev/config/
    export default defineConfig({
      plugins: [
        vue(),
        vueJsx(),
        dynamicBase({
          // dynamic public path var string, default window.__dynamic_base__
          publicPath: '',
          // dynamic load resources on index.html, default false. maybe change default true
          transformIndexHtml: false
        })
      ],
      resolve: {
        alias: {
          '@': fileURLToPath(new URL('./src', import.meta.url))
        }
      },
      base: '/static/',
    })
    

    Now everything works.