kit icon indicating copy to clipboard operation
kit copied to clipboard

Allow opting-out of loading specific dynamic component css

Open sviripa opened this issue 1 year ago • 2 comments

Describe the problem

When using dynamically imported components as suggested in this thread, css of all dynamically imported components is loaded.

Here's a link to the example repo and here it is deployed. On Foo page it renders two components so it is ok to load css bundles of all dynamically imported components. On Bar and Baz only one of the components is rendered but both css bundles are loaded.

Describe the proposed solution

I recognize that for the majority setups loading all css upfront is desired. Thus, I would like to propose a solution that does not change the default behaviour of SvelteKit and instead extends its api to give users a bit more control over css loading.

I suggest to add an additional function to handle server hook, similar to preload, that would be used to determine what files to should be loaded on the page. Example:

export async function handle({ event, resolve }) {
	const response = await resolve(event, {
		load: ({ type, path }) => type === 'css' || path.includes('/important/')
	});

	return response;
}

I implemented a draft PR for this functionality and would be happy to continue working on it if the suggested solution makes sense to SvelteKit's maintainers.

Alternatives considered

No response

Importance

i cannot use SvelteKit without it

Additional Information

No response

sviripa avatar Sep 24 '24 00:09 sviripa

I don't know what you think emailing maintainers achieves, but one thing it certainly doesn't do move your issue or PR to the top of the queue.

Conduitry avatar Oct 02 '24 00:10 Conduitry

According to the documentation, what you're describing is what preload is supposed to do:

preload(input: { type: 'js' | 'css' | 'font' | 'asset', path: string }): boolean — determines what files should be added to the <head> tag to preload it. The method is called with each file that was found at build time while constructing the code chunks — so if you for example have import './styles.css in your +page.svelte, preload will be called with the resolved path to that CSS file when visiting that page. Note that in dev mode preload is not called, since it depends on analysis that happens at build time. Preloading can improve performance by downloading assets sooner, but it can also hurt if too much is downloaded unnecessarily. By default, js and css files will be preloaded. asset files are not preloaded at all currently, but we may add this later after evaluating feedback.

My experience, however, is that this only affects the link header. The documentation implies this should be modifying which <link> elements appear in the <head> tag. Setting the preload callback to () => true and () => false makes no difference to the output of the generated <head>. Either the documentation is misleading, or preload isn't functioning as described. I have the exact same usecase as you, and the documentation implies that preload should work.

glyndwr-io avatar Oct 16 '24 04:10 glyndwr-io

@eltigerchino Unfortunately, I need to ask you to re-open this issue. I tried the fix added in https://github.com/sveltejs/kit/issues/13546 on my work project as well as the example repo and it didn't work.

Not exactly sure why, but my guess is that it's because we are importing our dynamic components inside +page.ts files, not inside *.svelte ones. We are following the approach suggested by @Rich-Harris in this comment.

For the example repo the following still stands:

  • Here's a link to the example repo and here it is deployed. On Foo page it renders two components so it is ok to load css bundles of all dynamically imported components. On Bar and Baz only one of the components is rendered but both css bundles are loaded.

sviripa avatar Apr 11 '25 20:04 sviripa

The example repo is different from the approach suggested by Rich.

In the example repo, it's using a dynamic import with a variable. This causes Vite to assume everything in that directory is being imported (since Vite can't know what component names are being passed from the server load function to the universal load function and into the dynamic import) and we are relying on Vite to tell us what is and isn't used on the server. Also, I don't know if there's a way to tell a layout "only inline X for route A and B, but don't inline X for route C" without running the code.

teemingc avatar Apr 15 '25 03:04 teemingc

I tried updating the example repo to not use variables in my dynamic imports but that didn't impact the behaviour. Here are the changes https://github.com/sviripa/sveltekit-dynamic-imports-example/commit/06703cd99f02e8787a276de4d59f334db29d0428

Thank you for taking a look!

sviripa avatar Apr 15 '25 13:04 sviripa