I have a node module dependency for theming content at node_modules/foo-styles.
For most css that I want to pull in, I can simply use an import 'foo-styles/dist/controls/button.css' in the page/component and vite does its magic, shoving the css where it fits best.
For theming however, I need to switch the included css variables file based on active theme in my <svelte:head> , e.g. reference foo-styles/dist/themes/{$theme}/color-variables.css in the markup.
To do so, I assume that vite must copy those files from node_modules/foo-styles to my apps asset directory without import magic, renaming of files etc.
I can only find examples for doing this with webpack or rollup using copy plugins ... is this something that vite can do out of the box? Is there a plugin available? How do you copy assets from node_module dependencies to the bundle?
You can make Vite copy assets and return a URL by adding ?url to the import. With this you then can just dynamically add a link to the <head> with said URL.
E.g.
import themeUrl from 'some-module/css/theme.css?url'
onMount(() => {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = themeUrl;
document.head.appendChild(link);
return () => link.remove();
});
If you do not want to manually list all theme imports, you can use Vite's glob import feature. Here the URL has to be written differently as it must start with / or ./:
const styles = import.meta.glob(
'/node_modules/some-module/css/*.css',
{ query: 'url', eager: true },
);
let selectValue = 'some-theme';
$: selectedStyle = `/node_modules/some-module/css/${selectedValue}.css`;
let link = null;
onMount(() => {
link = document.createElement('link');
link.rel = 'stylesheet';
document.head.appendChild(link);
return () => link?.remove();
});
$: if (link) {
const { default: href } = styles[selectedStyle];
link.href = href;
}
You can also use svelte:head, which can be simpler and will add the style reference during SSR, however the order of the stylesheets can be inconsistent as the style may be added before other styles on first load but added after these styles on navigation, so rules may be accidentally overridden.
<script>
const styles = import.meta.glob(
'/node_modules/some-module/css/*.css',
{ query: 'url', eager: true },
);
let selectValue = 'some-theme';
$: href = styles[`/node_modules/some-module/css/${selectedValue}.css`].default;
</script>
<svelte:head>
<link rel="stylesheet" {href} />
</svelte:head>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With