Skip to content

Entry points doesn't inline CSS, but client-side navigation might load another entry point #10285

@Tal500

Description

@Tal500

Describe the bug

I'm just forming the discussion started at #9761 (comment) in a hopefully well formed issue.

This issue is somewhere between a bug and a feature, the best way to see this is as "behavior that was fine and now was stopped working"(after PR #9761).

Problem

Since PR #9761, client side navigation on legacy mode is problematic.
For example, assume hypothetically you have a Nuxt website with the pages "/"(homepage) and "/about", each of them having some CSS.
The user may start in the page "/" and then navigate(**in the client side) to the page "/about", or the opposite, each of the option should be totally valid.
According to Vite, AFAIK, both of the pages are considered to be entry points.
If we're not on legacy mode, everything works well, since both on SSR and client-side navigation, the client always load the relevant <link> tags of the CSS files needed.

Assuming we're on legacy mode now.
On the first page the user load, there's no need to load JS-inlined CSS, since by SSR there are <link> tags referencing to the relevant CSS files. This was the motivation of PR #9761, that canceled CSS-inlining by JS for entry points, since they are already loaded by SSR.
But on our case, the SSR loads initially only the CSS files for the first page, but not to the second one.
When the user use the client side navigation to the second page, neither of the CSS files or the JS-inlined CSS is loaded! The former doesn't get loaded because we're on legacy mode, and the second isn't loaded because of PR #9761.

Solutions

As the last paragraph suggests, we have three possible solutions:

  1. Loading the CSS files like in modern mode. This is the most elegant solution in my opinion, and was done in PR feat: support preloading also on legacy bundle #9920.
  2. Revert PR perf: legacy avoid insert the entry module css #9761, which then will inline the CSS always on legacy, no matter if it's entry point or not. The problem of course is the original issue it solved, that the JS output will be larger since it contains the inlined-CSS, which is might be duplicated since the CSS files might be already loaded on SSR. Therefore, I suggest also the following next solution.
  3. Perform the CSS-inlining in a different JS file for each entry points. This way, on Vite preloading(which is essentially the Vite client-side navigation ability) in legacy mode, Vite will check if the CSS assets where already loaded, and only if not, Vite will import the JS file representing the relevant CSS-inlining. This way there the client will never (at the same session) need to load the same asset twice, once as CSS and once as JS.

Reproduction

See the code and the online preview in the readme desctiption(you need to use legacy browser for see the issue of CSS missing on navigation): https://github.com/Tal500/sveltekit-legacy-demo#online-preview

System Info

Not relevant.

Used Package Manager

npm

Logs

No response

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    p3-minor-bugAn edge case that only affects very specific usage (priority)plugin: legacyregressionThe issue only appears after a new release

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions