Jacob Palmer
Jacob Palmer

Reputation: 11

How to cross-load assets from separate site built with Vite as you would with Webpack in an HTML file?

I recently upgraded one of my projects from Vue-cli/Vue 2 over to Vue 3 and Vite for deployment. The app was deployed to an external server and works perfectly fine. However, the switch from vue-cli and webpack to vite has caused some issues.

This project is heavily reliant on Auth0 and Auth0 needs to be able to serve the page via cross-loading it from our server. Webpack worked great for this as just a very simple HTML file with some <script> tags served the site on the Auth0 domain. The index.html from my site was basically identical to the HTML that I put into Auth0 and it worked great, which is found below:

index.html from vue-cli/webpack:

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="icon" type="image/png" sizes="32x32" href="https://my-website-domain.com/favicon-32x32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="https://my-website-domain.com/favicon-16x16.png">
    <title>My Website</title>
    <link href="https://my-website-domain.com/js/app.js" rel="preload" as="script">
    <link href="https://my-website-domain.com/js/chunk-vendors.js" rel="preload" as="script">
</head>

<body class="font-sans antialiased"> <noscript> <strong>This site does not work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript>
    <div id="app"></div>

    <script type="text/javascript" src="https://my-website-domain.com/js/chunk-vendors.js"></script>
    <script type="text/javascript" src="https://my-website-domain.com/js/app.js"></script>
</body>

</html>

vue.config.js from vue-cli/webpack (the comments also provide some context on what the goal here is):

module.exports = {
    /*
     * This setting tells Vue to use the full URL for assets when it references them from the compiled JS.
     * This is critical for the page to work when served by Auth0's IdP on my-website.com --
     * it's cross-loading these assets from our-register, so if it's NOT using the full URL, the JS will fail
     * to load (since it doesn't exist on Auth0's server) and you'll get a white page.
     */
    publicPath: process.env.VUE_APP_PUBLIC_PATH,

    /*
     * Normally when building production, Vue will emit files with the name `app.{hash}.js`. This is a cache-
     * busting behaviour that is normally desirable. Vue automatically injects the correct names for the JS/CSS
     * into the index.html.
     * 
     * In our case, a copy of the index.html is hosted on Auth0's server as part of our config. We DO NOT update
     * this every time, so having `app.{hash}.js` instead of `app.js` will break the page when served from Auth0
     * at my-website.com. You'll get a white page and a CORB (yes, with a B) error.
     * 
     * Note that this setting ONLY changes the default behaviour of --mode=production. The subprod environments
     * default to false.
     */
    filenameHashing: false,
}

However, the app is now written as a module and Vite bundles and compiles the app differently than Webpackit. I need the app to be able to be served by Auth0, like in the html code above from the webpack/vue-cli version, but it seems I'm missing some key ideas about how Vite packages apps and module importing works. For the new Vite app, the index.html from the Vite deployment/build is below:

index.html from vite:

<!doctype html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
    <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
    <title>My Website</title>
  <script type="module" crossorigin src="/assets/index.js"></script>
  <link rel="stylesheet" crossorigin href="/assets/index.css">
</head>

<body class="font-sans antialiased">
    <noscript>
        <strong>This website does not work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>

    <div id="app"></div>
</body>

</html>

Here is my vite.config.js:

import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import mkcert from 'vite-plugin-mkcert'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
    mkcert()
  ],
  resolve: {
    extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  server: {
    https: true,
  },
  build: {
    rollupOptions: {
      output: {
        entryFileNames: `assets/[name].js`,
        chunkFileNames: `assets/[name].js`,
        assetFileNames: `assets/[name].[ext]`
      }
    }
  }
})

TLDR; In theory, like with webpack, my (likely naive) thought process is that I can use the above html from the Vite build in my auth0 to cross-load the assets from my main site like I did with webpack previously but it does not seem to work like that.

One idea I've tried to do is making the href and src paths in <link> <script> on the new Vite HTML to use the full public path (https://my-website/assets/index.js) rather than a local path on the server (/assets/index.js) since those assets don't exist on Auth0 servers (hence the cross-loading necessity). For one, I can't figure out how to make Vite build the dist with all these assets referencing the full URL path. Furthermore, it doesn't seem like that would even work as I tried manually changing these paths and running the simple html and it couldn't properly/reach the hosted sites assets, so I believe I'm clearly missing something vital here about how to cross-load modules like this.

Upvotes: 0

Views: 594

Answers (1)

Josh
Josh

Reputation: 4322

I came across a similar issue with Vite. Have you tried setting the base option in vite.config.js?

Setting this property to the full domain of the production webserver solved the problem for me.

// vite.config.js
export default defineConfig({
    base: "https://www.your-domain.com",
    // other config...
});

Upvotes: 0

Related Questions