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

Enhance Vite serve so it can be used with single-spa #14000

Closed
4 tasks done
webJose opened this issue Aug 1, 2023 · 3 comments
Closed
4 tasks done

Enhance Vite serve so it can be used with single-spa #14000

webJose opened this issue Aug 1, 2023 · 3 comments

Comments

@webJose
Copy link

webJose commented Aug 1, 2023

Description

If you have ever used single-spa, you have most likely gained a taste for import maps and the ability to replace pieces of front-end at will. Furthermore, you most likely have tried at least once to make a regular Vite project work with single-spa because create-single-spa is very limited in terms of project options. For example, you cannot create Vite TypeScript projects with create-single-spa.

Vite can in fact, as of today and for some good time now, create a built version that works with single-spa. However, as of today, the recommended single-spa setup doesn't work while in development using vite serve: The assets are not properly served.

I am proposing (and I think I can make this PR) to give vite serve the ability to continue to work as usual but ensuring asset URL's are properly re-written using full URL bases, which is what works with single-spa's recommended setup.

Problem Details

To understand the problem, let's understand single-spa's recommended setup:

  1. In the root project, define import maps for the entry points of all micro-frontends. Usually, these are absolute URL's that start with a prefix unique to the micro-front end. Example: "@scope/mifeA": "/mifeA/spa.js". While in development, however, these usually are full URL's. Example: "@scope/mifeA": "http://localhost:4222/spa.js".
  2. In the micro-frontend project, tell Vite to use the base property to re-write the asset URL's to include either the micro-fronted prefix when deploying, or to include the full URL if serving. This is where all falls apart.

Yes, Vite respects the base given by the developer while building (vite build), but not while serving. While serving, the base loses its scheme, host and port and is trimmed down to its path. At this point, the root project can load the micro-frontend because the import map specifies the full URL, but the imported HTML and JavaScript contain asset URL's that were re-written using only the path of the full URL specified in base, not the full URL. The net result: The micro-frontend loads, but assets do not load.

Suggested solution

Vite's base configuration property undergoes a resolution process. In config.ts, line 872 we find the resolveBaseUrl() function. This function is used during configuration resolution and its purpose is to normalize the URL, be it relative or absolute.

On the other hand, we have base.ts that uses the base after it has gone through the resolution process. This usage of the base clearly requires a base without scheme, host and port, and as far as I can tell, is the only reason why resolveBaseUrl() does what it does, but please correct me if I'm mistaken.

The solution I propose seems to be simple enough. This what is seen inside resolveBaseUrl() in config.ts, line 900:

  // parse base when command is serve or base is not External URL
  if (!isBuild || !isExternal) {
    base = new URL(base, 'http://vitejs.dev').pathname
    // ensure leading slash
    if (base[0] !== '/') {
      base = '/' + base
    }
  }

The first step of the solution is to remove the !isBuild condition from the IF statement. This way, external (full) URL's will no longer be trimmed down to its path, which should produce an output with asset URL's containing the full base, which is what the single-spa scenario needs.

This step alone breaks the base server middleware, so the next step would be to trim down the base to its pathname inside the middleware. base.ts, line 15 is:

const base = config.rawBase

If we changed this to:

const base = (new URL(config.rawBase, 'http://vitejs.dev')).pathname

Then the middleware should be back in business.

Alternative

The only alternative that I have devised so far is to configure the root's Vite server with proxies for each micro-frontend. This works for the case where you are running the entire front-end locally in your PC, but it doesn't work when you want to use single-spa's recommended setup when working a single micro-frontend which is: To open the application from a deployed source (pre-production environment, for example), and then use the import-map-overrides package to override the import map entry for the micro-frontend that needs maintenance. In this scenario, the overridden micro-frontend loads, but the assets don't load or the loaded assets come from the deployed environment, not from the developer's local PC.

Additional context

No response

Validations

@webJose
Copy link
Author

webJose commented Aug 9, 2023

Hello, contributors and members. What does the lack of activity mean for this issue?

  1. We haven't had the time to look at it.
  2. We looked at it but sparks no interest.
  3. Other.

I would like to know because I have never participated in open source before. I don't know how to proceed. I don't want to come across as impatient. I am asking because I see all these newer issues that have come after this one with activity. This makes me wonder if I should have done my issue differently.

Your feedback is welcome. The outcome of this issue will help me define the course of action I should take with my vite-plugin-single-spa project. Thank you in advance.

@Je12emy
Copy link

Je12emy commented Oct 18, 2023

I'm also interested in this feature!

@sapphi-red
Copy link
Member

I guess server.origin would work.
Closing as I also found that you have made it work with that: #13927 (reply in thread)

@github-actions github-actions bot locked and limited conversation to collaborators Nov 22, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants