Open Richard-Walton opened 1 year ago
Yeah Vite currently doesn't handle this case too well in dev. The right configuration would be base
and that should work in build, however in dev, we always truncate http://something/
to /
to simplify loading things in dev. The expectation was that a full URL base
is mainly for the prod URL only.
This would be hard to support though and requires refactoring many parts of the codebase.
@bluwy Crumbs! Are you able to advise of any workaround I could implement? Some kind of post processing html plugin? Failing that I can rewrite the responses in my load balancer but I'd prefer a vite centric solution if possible.
Many thanks
You can write a Vite plugin and use the transformIndexHtml
hook to prepend the host, something like:
const plugin = {
name: '',
transformIndexHtml: {
order: 'post', // after vite modifies the links
handler(html) {
// parse and replace the links
return html
}
}
}
I'm not sure if there's more to this though, presumably the existing scripts should work without the explicit hostname as they're already fetched relatively to the hostname they're loaded from.
I wrote a plugin inspired by the comment above and it worked well, there are some changes more than the transform though. I use Vite dev server with middleware mode so the @vite/client
handling part might be different.
export const vitePluginRewriteBase = (viteRealBase: string): Plugin => {
const viteFakeBaseForVitePluginRewriteBase = "/VITE_PLUGIN_REWRITE_BASE_PATH";
const viteFakeBaseRegex = new RegExp(viteFakeBaseForVitePluginRewriteBase, "g");
return {
name: "vite-plugin-rewrite-base",
apply: "serve",
config(config) {
config.base = viteFakeBaseForVitePluginRewriteBase;
},
transform: {
order: "post",
handler(code, id) {
// Handle `import "@vite/client"` which is the HMR client
if (id.endsWith("node_modules/vite/dist/client/client.mjs")) {
// Don't rewrite the base here, because Vite HMR's middleware listens on ws://.../<vite config's base>
return code;
}
// Rewrite all other bases in the code to make sure they point to Vite dev server's domain.
// This is mainly fixing URL references in CSS to make them point to the Vite dev server,
// because CSS code will be injected to the main page on load,
// making the base point to the backend server (=where the main page is served) instead of the Vite dev server if we don't rewrite them,
// so here we write to make sure those relative paths become absolute path with the Vite dev server's domain.
return code.replace(viteFakeBaseRegex, viteRealBase);
},
},
transformIndexHtml: {
order: "post",
handler(html) {
// Rewrite to make sure the assets are pointed to Vite dev server.
// Because the HTML is served by the backend, relative paths are pointed to the backend instead of the Vite dev server.
// Therefore we rewrite the relative path to absolute path with the Vite dev server's domain here.
return html.replace(viteFakeBaseRegex, viteRealBase);
},
},
};
};
then in the config:
import { vitePluginRewriteBase } from "./vitePluginRewriteBase";
defineConfig(({ command }) => ({
plugins: [
vitePluginRewriteBase(viteDevServerUrl),
],
}))
Description
I have a slightly unusual dev environment where I run multiple versions of a vite application behind a load balancer.
To access the application I goto my dev host: e.g. http://mydev?version=1 or http://mydev?version=2 The load balancer then directs traffic to appropriate application running on the
mydev
host (A locally running VM)A request to load the app is therefore handled as follows:
http://mydev?version=1 -> load-balancer:80 -> node-backend-server:1000 -> vite-frontend-server:1111
or
http://mydev?version=2-> load-balancer:80 -> node-backend-server:2000 -> vite-frontend-server:2222
The vite server responds with HTML which, no matter now hard I try, contains relative urls. These relative urls result in 404s as the node-backend-server cannot handle the requests.
An example HTML generated by vite (with comments explaining what I would like to happen)) looks like:
I have tried setting base to
http://mydev:<frontend-port>
but that didn't work. I have tried setting base to:<frontend-port>
but that didn't work. I have tried using the experimentalrenderBuiltUrl
but that didn't work.Before using vite, we used webpack and were able to get things working using their
publicPath
option (Setting it tohttp://mydev:<frontendport>
Suggested solution
Script tags in index.html should be configurable using an absolute base url
Alternative
No response
Additional context
No response
Validations