Open AlexMargk2112 opened 2 years ago
Any idea how to do the lazy loading sass files with vite?
Hi!
I am the same as @AlexMargk2112 . This is my personal github account.
I dont know what lazy exactly would be but i kind of made a helper function that returns an object with 2 functions( use(), unuse() ) that are used by your addon.
In the use()
funtcion i am using the concept of dynamic import const file = import(filePath)
The code it looks like this
import cssVariablesTheme from '@etchteam/storybook-addon-css-variables-theme';
export const decorators = [cssVariablesTheme];
const createStyleTags = (url) => {
return {
styleTag: null,
innerStyles: '',
use: async function () {
if (!this.styleTag) {
this.styleTag = document.createElement('style');
this.styleTag.type = 'text/css';
this.innerStyles = (await import(url)).default;
this.styleTag.innerHTML = this.innerStyles;
document.body.appendChild(this.styleTag);
return;
}
this.styleTag.innerHTML = this.innerStyles;
},
unuse: function() {
if (this.styleTag) {
this.styleTag.innerHTML = '';
}
}
}
}
const theme1 = createStyleTags('../src/assets/themes/theme1.scss?inline');
const theme2 = createStyleTags('../src/assets/themes/theme2.scss?inline');
export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
cssVariables: {
files: {
'Theme ONE': theme1,
'Theme TWO': theme2,
},
},
};
The code might not be perfect but this was my first idea to create something similar like the webpack loader.
I have also made a repo with a minimum Storybook - Vue - @storybook/builder-vite to reproduce the proof of concept. repo
I have noticed though an issue when changing the theme. Sometimes the current selected theme is not updated at the themes tab but after checking previous projects that are using Webpack i saw that the issue is also there so thats not vite relative issue.
Kind regards , Alexander
@AlexanderMar21 Thank you for your solution, but it's not working for me correct. Theme doesn't switch after first change. I changed your code a bit and got a working solution
const cssVariablesViteHack = (url: string) => {
return {
styleTag: null as any,
innerStyles: '',
use: async function () {
if (!this.styleTag?.innerHTML) {
this.styleTag = document.createElement('style');
this.styleTag.type = 'text/css';
this.innerStyles = (await import(/* @vite-ignore */ url)).default;
this.styleTag.innerHTML = this.innerStyles;
document.body.appendChild(this.styleTag);
return;
}
this.styleTag.innerHTML = this.innerStyles;
},
unuse: function () {
if (this.styleTag) {
this.styleTag.innerHTML = '';
}
}
};
};
I kept running into issues with the above switching between stories. Vite also adds some <style />
in development builds it seems. This works like a charm on my end.
/**
* Create and place <style /> in document
*/
const styleTag = document.createElement('style');
styleTag.type = 'text/css';
document.head.appendChild(styleTag);
/**
* Utility method to inject and cleanup style sheets
*/
export const createStyleTags = (url: string) => {
return {
use: async function () {
// Update innerHtml with stylesheet data
if (styleTag.id !== url) {
styleTag.id = url;
styleTag.innerHTML = (await import(/* @vite-ignore */ url)).default;
}
},
unuse: function () {
/**
* <style /> tag that vite loads into the document head
* These are identified by the style tag containing data-vite-dev-id attribute
*/
Array.from(document.head.querySelectorAll('style[data-vite-dev-id]')).forEach((styleTag) => styleTag.remove());
},
};
};
When I try to implement this workaround it works for some css files. However when I try to load a css from node _modules I get:
Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/css". Strict MIME type checking is enforced for module scripts per HTML spec.
When I copy that file to my .storybook folder and load it from there it does work Any ideas?
Hmm all of the solutions only works on first load for me. As soon as i change story or any of the controls that affect color, it dissapears
I have similar problems. It seems to be that switching stories use
es your current theme, and then also unuse
es that same theme. Workarounds like @magersoft present cause the style tag to be emptied by that unuse
call.
A workaround I'm currently investigating is creating a single style tag, and only listening to use
calls:
const makeCssFiles = themes => {
const styleTag = document.createElement('style');
document.body.appendChild(styleTag);
const use = name => () => {
const { [name]: styles } = themes;
styleTag.innerHTML = styles;
};
return Object.fromEntries(
Object.keys(themes).map(name => {
return [name, { use: use(name), unuse: () => null }];
}),
);
};
With this usage:
import lightTheme from 'lightTheme.css?inline';
import dark from 'darkTheme.css?inline';
export const parameters = {
cssVariables: {
files: makeCssFiles({
Light: lightTheme,
Dark: darkTheme
}),
defaultTheme: 'Light'
}
}
Let me know whether that works for you ^^.
@lennartbuit This works great locally, but unfortunately not with a static build, not sure why.
@simonhermann yes, I have the same problem in static build. I'll try fix this problem, but nothing yet. If you find some decisions, please share it here.
After following the click event with the debugger I got stuck at the cssVariablesChange
event that is emitted but not received. I'm not an expert in storybooks manager api that handles these messages. Maybe someone else has any idea on how we can fix this?
The cssVariablesChange
event is emitted from this line:
emit('cssVariablesChange', { id: newValue });
https://github.com/etchteam/storybook-addon-css-variables-theme/blob/2b5505db0d47b184da78db6832587d9494c2eac4/src/register.tsx#L71
And should be received in this line:
channel.on('cssVariablesChange', ({ id }: { id: string }) =>
https://github.com/etchteam/storybook-addon-css-variables-theme/blob/2b5505db0d47b184da78db6832587d9494c2eac4/src/index.ts#L75
Hi,
i ve been using storybook till now with webpack builder. I tried switching to "Vite" which is significantly faster but not all the storybook plugins work as expected. The documentation of "@etchteam/storybook-addon-css-variables-theme" of suggests using loaders which are made for webpack. Will in future will be @storybook/builder-vite support for this plugin?