vikejs / vike

🔨 Flexible, lean, community-driven, dependable, fast Vite-based frontend framework.
https://vike.dev
MIT License
3.88k stars 334 forks source link

Relative base such as `./` #606

Open brillout opened 1 year ago

brillout commented 1 year ago

Description

Vite supports setting base to ./ for "embedded deployments", see vite.config.js#base. Can Vike support such relative base paths?

brillout commented 1 year ago

It isn't clear whether this is possible, let alone whether it makes sense. (Vite apps usually have only one URL while Vike apps usually have several URLs.)

Previous discussions making it clear that relative base paths don't make sense in the context of an app with mutliple URLs:

brillout commented 8 months ago

Problem

When pre-rendering, because the HTML is set in stone, static assets need to be referenced with relative paths (e.g. ../../assets/* instead of /assets/*). Same for links.

  <!-- URL (logical): / -->
  <!-- URL (real, example 1): /some-base/ -->
  <!-- URL (real, example 2): /some/nested/base/ -->
  <img src="./assets/logo.aeuh81a.svg" />
  <a href="./about-us" />
  <!-- URL (logical): /product/edit/42 -->
  <!-- URL (real, example 1): /some-base/product/edit/42 -->
  <!-- URL (real, example 2): /some/nested/base/product/edit/42 -->
  <img src="../../assets/logo.aeuh81a.svg" />
  <a href="../../about-us" />

Solution

import { makeUrlRelative } from 'vike'
import { usePageContext } from 'vike-{react,vue,solid}'
import logoUrl from './logo.svg'

function SomeComponent() {
  const pageContext = usePageContext()
  return <>
    <a href={makeUrlRelative('/product/42', pageContext)} />
    <img src={makeUrlRelative(logoUrl, pageContext)} />
  </>
}

Contribute

Remarks

brillout commented 7 months ago

It isn't clear whether this is possible, let alone whether it makes sense

Therefore closing.

lsegal commented 7 months ago

Fun timing on this one, I just came across this limitation when trying to use Vike for a project. The lack of support here is a little bit of a blocker for my use case in which the app is served by Vite/Vike via SSG and exposed indirectly via a proxy attached to arbitrary base paths-- in particular, there is no one specific fixed path, and it is chosen entirely by the proxy, not the application sitting behind it. Think about it like this (it's not exactly this, but this use case would fail in the same way): I'm generating a self contained application that is vended out to third parties all over the Internet and will be hosted in a white label fashion on various external properties at various locations. The static generation is an important piece to this limitation, as this works fine via SSR (since we can hijack routing) but breaks when generating static files. Unfortunately, static pre-render generation was the entire purpose for using Vike in the first place.

A lot is being mentioned about "assets", and I'm not entirely sure if Vike classifies its own chunks/compiled assets as "assets" in the same sense, but in my case, the big issue that breaks are the <script> tags, which I am assuming(?) is managed by Vike(?).

image

It isn't clear whether this is possible

I'm a little confused about the "possible" statement, as surely it is explicitly "possible" to generate relative links between documents (certainly this is a well known and very-solved problem). Is there some Vite API getting in the way? If so, that seems odd, since Vite itself supports a relative base.

Are there any workarounds for this use case, or is Vike not going to work for this use case?

brillout commented 7 months ago

I agree your use case makes sense. What isn't clear is whether it's feasible to achieve that without ending up with a frankenstein (e.g. relative links are fundamentally broken in multi-page React/Vue/... apps).

Is there any React/Vue/... SSR framework out there that supports relative base paths? I honestly doubt it, but I'm happy to be shown wrong.

Also sponsoring welcome (you'll get a bump in priority).

jwahdatehagh commented 7 months ago

It isn't an option to let the user always define relative relatives because it's very brittle: for example a component function LinkProducts() { return List of Products } breaks for the route /product/edit/42 (the correct path for that route is ../../products/).

Couldn't this be handled within a <RouterLink> component (or similar)?

The logic doesn't seem too wild to me: Prepend links with ./ and then a ../ for every nesting level before linking to assets or pages?

I could have sworn this existed in Nuxt once but it's broken there rn.

Relevant for static deployments to e.g. IPFS, since you don't know the path the deployment ends up in before building.

brillout commented 7 months ago

Couldn't this be handled within a <RouterLink> component (or similar)?

This would also need to applied to references to static assets, e.g. <img src="../../../assets/logo.e19uaha.svg">. That said, this could indeed be a solution. Although it isn't as simple as it seems, see updated problem statement.

The logic doesn't seem too wild to me: Prepend links with ./ and then a ../ for every nesting level before linking to assets or pages?

PR welcome if you want to give it a try yourself.

brillout commented 6 months ago

Another use case: https://github.com/vikejs/vike/issues/1223#issuecomment-1858843408.

brillout commented 5 months ago

Re-opening as there seem to be a solution for this.

CookedApps commented 5 months ago

We are currently experiencing challenges regarding this issue. Our use case involves deploying our React application in two distinct environments, each with unique requirements:

1) As a pre-rendered MPA on Cloudflare Pages. This deployment has a fixed base path, needs to be crawlable and optimized for search engines.

2) Embedded within an iframe on our partner's website. In this scenario, the application doesn't need to be crawlable and could potentially operate as an SPA without the pre-rendering, although pre-rendering is preferred for improved loading times. A significant challenge here is the base path, as the app is hosted at a randomly generated path after each deployment which is beyond our control, requiring relative base path support on our end.

We really need support for a relative base path in Vike, or a feasible workaround (possibly without pre-rendering?) for the second mentioned environment. So this issue is a critical deal-breaker for us.

If we can ensure that the necessary support will be available before June, I am willing to provide financial support for the project as well, as Vike is an otherwise perfect fit for our needs. 🙌

brillout commented 5 months ago

@CookedApps

So this issue is a critical deal-breaker for us.

I see.

If we can ensure that the necessary support will be available before June, I am willing to provide financial support for the project as well

While I beileve the aforementioned solution will work, there are quite a lot of higher priority things in the pipeline, especially given that I foresee the implementation to be far from trivial. So I'm not sure how much sponsoring would help, but it depends on how much you'd be willing to sponsor. Feel free to PM us.

Also, what would help is doing some research wehther other frameworks support that. It would help us a lot to see a real world solution to this.

CookedApps commented 5 months ago

I see why this is a problem for MPAs and SSR environments. But I wonder if it would be possible to make relative base paths work in an SPA. For our use case we only need relative base path support for one customer specific deployment where we don't need to support pre-rendering, SSR nor being crawlable in the first place.

Therefore, switching the entire Vike app to SPA "mode" + client side routing should technically allow us to add a relative base path, right?

brillout commented 5 months ago

@CookedApps I'm reluctant to work on a solution that would work for only a small minority of users, even if it means less work.

CookedApps commented 5 months ago

@brillout I understand and respect your stance on not focusing on features for a minority of users. I'm not expecting you to invest time in our specific issue, but I would appreciate any guidance or suggestions for possible workarounds.

I'm also open to contributing to Vike directly and enrich the framework by adding such functionality. A bit of initial direction from the maintainers would be really helpful, as I'm currently finding it challenging to get involved, despite my enthusiasm for the project.

Thanks for considering this!