Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support base url with port for scripts in index.html #14263

Closed
4 tasks done
Richard-Walton opened this issue Sep 2, 2023 · 5 comments
Closed
4 tasks done

Support base url with port for scripts in index.html #14263

Richard-Walton opened this issue Sep 2, 2023 · 5 comments
Labels
duplicate This issue or pull request already exists

Comments

@Richard-Walton
Copy link

Richard-Walton commented Sep 2, 2023

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 themydev 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:

<!doctype html>
<html lang="en">
  <head>
    <script type="module" src="/@vite/client"></script> <!-- THIS  IS THE PROBLEM -->
    
    <!-- I WOULD LIKE VITE TO GENERATE THIS -->
    <script type="module" src="http://mydev:<FRONTEND_PORT>/@vite/client"></script> 

  </head>
  <body>
    <script type="module" src="/src/main.tsx"></script> <!-- SAME ISSUE -->
        <!-- I WOULD LIKE VITE TO GENERATE THIS -->
    <script type="module" src="http://mydev:<FRONTEND_PORT>/src/main.tsx"></script> 
  </body>
</html> 

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 experimental renderBuiltUrl but that didn't work.

Before using vite, we used webpack and were able to get things working using their publicPath option (Setting it to http://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

@Richard-Walton Richard-Walton changed the title Support base url with port Support base url with port for scripts in index.html Sep 4, 2023
@bluwy
Copy link
Member

bluwy commented Sep 4, 2023

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.

@Richard-Walton
Copy link
Author

@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

@bluwy
Copy link
Member

bluwy commented Sep 5, 2023

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.

@arthow4n
Copy link

arthow4n commented Mar 22, 2024

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),
	],
}))

@sapphi-red
Copy link
Member

Duplicate of #18457

@sapphi-red sapphi-red marked this as a duplicate of #18457 Nov 12, 2024
@sapphi-red sapphi-red closed this as not planned Won't fix, can't repro, duplicate, stale Nov 12, 2024
@sapphi-red sapphi-red added duplicate This issue or pull request already exists and removed enhancement: pending triage labels Nov 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate This issue or pull request already exists
Projects
None yet
Development

No branches or pull requests

4 participants