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

Duplicate CSS rules after build #10379

Closed
stefandevai opened this issue Jul 13, 2023 · 7 comments · Fixed by #10442
Closed

Duplicate CSS rules after build #10379

stefandevai opened this issue Jul 13, 2023 · 7 comments · Fixed by #10442
Labels
bug Something isn't working

Comments

@stefandevai
Copy link

Describe the bug

Hello everyone!

I'm building a personal blog and for for some reason the link tags containing css files are duplicated in production only. In dev mode everything looks fine. For this reason, every style is duplicated.

I've created a repo and added only @sveltejs/adapter-static and the issue remained.

Thanks in advance.

Reproduction

https://github.com/stefandevai/duplicated-css

  • Build the package
  • Serve the static files generated on the build directory
  • Open the example in a browser (tested with firefox and chrome) and inspect the orange title
  • The CSS rule background: orange; is shown twice

image

Logs

No response

System Info

System:
    OS: macOS 10.15.7
    CPU: (4) x64 Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz
    Memory: 565.56 MB / 4.00 GB
    Shell: 5.7.1 - /bin/zsh
  Binaries:
    Node: 19.9.0 - ~/.nvm/versions/node/v19.9.0/bin/node
    Yarn: 1.22.17 - /usr/local/bin/yarn
    npm: 9.6.3 - ~/.nvm/versions/node/v19.9.0/bin/npm
  Browsers:
    Chrome: 114.0.5735.198
    Safari: 15.4
  npmPackages:
    @sveltejs/adapter-auto: ^2.0.0 => 2.1.0 
    @sveltejs/adapter-static: ^2.0.2 => 2.0.2 
    @sveltejs/kit: ^1.20.4 => 1.22.3 
    svelte: 4.0.5 => 4.0.5 
    vite: ^4.4.2 => 4.4.3

Severity

serious, but I can work around it

Additional Information

No response

@performautodev

This comment was marked as spam.

@ghostdevv
Copy link
Member

I believe this is because in the SSR output we have a link tag, and it's also being added by the hydration step. I don't think this would be considered a bug, or even fixed - I myself am not sure how to. At the very least I wouldn't worry about it since it's not causing duplicated network requests 🙏

@stefandevai
Copy link
Author

It's a bit annoying regarding DX. When creating layouts, I usually iterate a lot of possibilities in the browser dev tools before writing the actual CSS. When the CSS is duplicated, I have to turn off CSS rules two times. I also don't think it's normal, I spent quite some time debugging believing it was an issue on my end.

@stefandevai
Copy link
Author

Taking a look at the source code I found two parts that seem to be related to the issue.

The comments mention double parsing in Chromium and double requests in Firefox. I tried changing the preloadStrategy option but the issue persisted.

output?: {
/**
* SvelteKit will preload the JavaScript modules needed for the initial page to avoid import 'waterfalls', resulting in faster application startup. There
* are three strategies with different trade-offs:
* - `modulepreload` - uses `<link rel="modulepreload">`. This delivers the best results in Chromium-based browsers, in Firefox 115+, and Safari 17+. It is ignored in older browsers.
* - `preload-js` - uses `<link rel="preload">`. Prevents waterfalls in Chromium and Safari, but Chromium will parse each module twice (once as a script, once as a module). Causes modules to be requested twice in Firefox. This is a good setting if you want to maximise performance for users on iOS devices at the cost of a very slight degradation for Chromium users.
* - `preload-mjs` - uses `<link rel="preload">` but with the `.mjs` extension which prevents double-parsing in Chromium. Some static webservers will fail to serve .mjs files with a `Content-Type: application/javascript` header, which will cause your application to break. If that doesn't apply to you, this is the option that will deliver the best performance for the largest number of users, until `modulepreload` is more widely supported.
* @default "modulepreload"
*/
preloadStrategy?: 'modulepreload' | 'preload-js' | 'preload-mjs';
};

This part is also relevant. Somehow it seems that this loop runs twice and the link tags are added each time.

for (const path of included_modulepreloads) {
// see the kit.output.preloadStrategy option for details on why we have multiple options here
link_header_preloads.add(`<${encodeURI(path)}>; rel="modulepreload"; nopush`);
if (options.preload_strategy !== 'modulepreload') {
head += `\n\t\t<link rel="preload" as="script" crossorigin="anonymous" href="${path}">`;
} else if (state.prerendering) {
head += `\n\t\t<link rel="modulepreload" href="${path}">`;
}
}

@ghostdevv
Copy link
Member

It's a bit annoying regarding DX. When creating layouts, I usually iterate a lot of possibilities in the browser dev tools before writing the actual CSS. When the CSS is duplicated, I have to turn off CSS rules two times. I also don't think it's normal, I spent quite some time debugging believing it was an issue on my end.

Iirc the issue is only present after building with static adapter?

@eltigerchino eltigerchino added bug Something isn't working and removed pkg:adapter-static labels Jul 23, 2023
@eltigerchino
Copy link
Member

eltigerchino commented Jul 23, 2023

@stefandevai A temporary workaround is to turn off SSR or set svelte.config.js config.kit.paths.relative to true or false.

// routes/+layout.svelte
export const prerender = true;
export const ssr = false;

I tested and it seems to happen to the node adapter too. Currently only affects Chrome and Firefox (Safari on macOS doesn't parse the stylesheet twice). I'm not sure how to fix this but maybe Kit can always set SSR to false if prerender is true?

EDIT: seems this isn't related to prerendering at all. It happens when csr and ssr are both true (as pointed out by Ghost). I wonder if we can check if both options are enabled, then only load the stylesheets once (or check if they're already in the <head>)

@eltigerchino eltigerchino changed the title CSS is linked twice with @sveltejs/adapter-static on production builds duplicate CSS rules after build Jul 23, 2023
@eltigerchino eltigerchino changed the title duplicate CSS rules after build Duplicate CSS rules after build Jul 23, 2023
@eltigerchino
Copy link
Member

Seems like Vite is responsible for adding the <link> tags to the head in addition to what SvelteKit is already adding. I'm not sure if this is intended behaviour? I can't seem to figure out how to prevent Vite from doing so (and what negative effects there may be if any).

dummdidumm pushed a commit that referenced this issue Jul 31, 2023
fixes #10358
fixes #10379
The path optimization was applied too often, causing relative/absolute path mismatches, causing Vite to add duplicate link module preloads
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants