Search code examples
sassvuejs3viterollup

Vite + Vue 3, font-face urls point to the wrong location after building


When I build my vue application using vite build I get a build folder containing the fonts, .css and .js files as expected. However, my fonts are in my shared folder, which is directly under the root of my project.

- /project/
    - /src/
      - /styles/
        - /fonts/
           - fonts.scss
        - main.scss
      - main.ts
    - /shared/
      - /fonts/

- vite.config.ts

In my fonts.scss I reference to the fonts as follows (this file is imported by my main.scss:

$browser-font-path: '@shared/fonts';

@font-face {
  font-display: auto;
  font-family: 'test';
  font-style: normal;
  font-weight: 400;
  src: url('#{$browser-font-path}/test.eot');
  src: url('#{$browser-font-path}/test.eot?#iefix')
      format('embedded-opentype'),
    url('#{$browser-font-path}/test.woff2')
      format('woff2'),
    url('#{$browser-font-path}/test.woff') format('woff'),
    url('#{$browser-font-path}/test.ttf')
      format('truetype');

My vite.config.ts looks as follows:

export default ({ mode }: { mode: string }): UserConfig => {
  process.env = { ...process.env, ...loadEnv(mode, process.cwd()) };

  return defineConfig({
    plugins: [
      vue({})
    ],
    build: {
      target: 'esnext',
      manifest: true,
      outDir: './my-build-dir-path',
      rollupOptions: {
        input: `./src/main.ts`,
        output: {
          entryFileNames: '[name].js',
          chunkFileNames: '[name]-[hash].js',
          assetFileNames: '[name].[ext]',
          globals: {
            vue: 'Vue'
          }
        }
      }
    },
    resolve: {
      alias: {
        '@shared': '/shared',
        '@': '/src'
      }
    }
  });
};

However, when I build this, the built main.css gives the error that my font files cannot be found, because it is looking at the root /, instead of my provided built directory. It doesnt look at the right place, how can I fix this?


Solution

  • I found the solution to the problem. In the Vite documentation is mentions:

    enter image description here

    https://vitejs.dev/config/shared-options.html#base

    So what I ended up doing was add the base propety with an empty string to the top of my config like shown below:

    export default ({ mode }: { mode: string }): UserConfig => {
      process.env = { ...process.env, ...loadEnv(mode, process.cwd()) };
    
      return defineConfig({
        base: '', // <-- add this to the top of the line to use for embedded deployment
        plugins: [
          vue({})
        ],
        build: {
          target: 'esnext',
          manifest: true,
          outDir: './my-build-dir-path',
          rollupOptions: {
            input: `./src/main.ts`,
            output: {
              entryFileNames: '[name].js',
              chunkFileNames: '[name]-[hash].js',
              assetFileNames: '[name].[ext]',
              globals: {
                vue: 'Vue'
              }
            }
          }
        },
        resolve: {
          alias: {
            '@shared': '/shared',
            '@': '/src'
          }
        }
      });
    };