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
Add loader for .module.css to load CSS modules #6055
Comments
Hey @manuelbieh - one particularly simple way to get css modules working in your storybook is to add react scripts to the project. Storybook should then pick up on your Doing so enables With that being said, adding Caveat: I've found this to be almost perfect for my needs building a gatsby/storybook project for thegymnasium.com. The unfortunate problem I'm having at the moment is that Gatsby and Storybook process modules differently - you can see my dilemma here. |
Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks! |
@manuelbieh This is a great feature. However, I don't want to add any more dependencies to Storybook (in fact, I'd like to start removing them!). Last year @igor-dv developed a feature called "presets" which is perfect for this. It's a solution that can modify your webpack/babel configs and more by adding a single line to |
Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks! |
Hey there, it's me again! I am going close this issue to help our maintainers focus on the current development roadmap instead. If the issue mentioned is still a concern, please open a new ticket and mention this old one. Cheers and thanks for using Storybook! |
@manuelbieh FYI we merged the presets doc and released our first preset. #5333 Any interest in doing this for CSS modules? If so, I'd def feature it as part of the push towards presets. |
Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks! |
Hey there, it's me again! I am going close this issue to help our maintainers focus on the current development roadmap instead. If the issue mentioned is still a concern, please open a new ticket and mention this old one. Cheers and thanks for using Storybook! |
@manuelbieh Any interest in pairing on a CSS modules preset? I'm familiar with the presets side and it sounds like you're familiar with the CSS modules side. I bet we could get something going in 30m if you're interested. |
@shilman Hey, sure. Just let me know how I can help. I just googled the concept of presets in Storybook, looks awesome. I guess the preset will probably look similar to what I've already done here, right? https://github.com/manuel-bieh/ui/blob/master/config/webpack.config.js/storybook.js |
@manuelbieh Yeah, we can probably just copy and paste from that. Want to hop on our discord and pair on it? Or if you can explain to me how to use it / test it, I can probably just whip something out. |
I'm currently setting CSS Modules in a shared component library written in TypeScript (apps consuming this library already use CSS Modules, but the shared library doesn't) and I ended up with this: config.module.rules.find(
rule => rule.test.toString() === '/\\.css$/',
).exclude = /\.module\.css$/;
config.module.rules.push({
test: /\.module\.css$/,
use: [
'style-loader',
'css-modules-typescript-loader',
{
loader: 'css-loader',
options: {
modules: true,
},
},
],
}); It's a work in progress for a few reasons which I assume are on our end (e.g. the build fails the first time because
Unfortunately, our Webpack config does something additional that the preset would not do (see below) so depending on the capabilities to extend / hook into / compose presets, we would or would not be able to use it. If not, then excluding Thanks for your hard work! If anyone is interested about what we do in the Webpack config: config.plugins.push(
new DefinePlugin({
'process.env.GIT_REVISION': JSON.stringify(
execSync('git describe')
.toString()
.trim(),
),
}),
); This exposes a human-readable git revision to the build, which we then use for a couple things, such as setting a link to the component library repo using the theme
That offers a quick way to know the current version one is looking at, among other things. |
@astorije thanks for the solution, we don't have Typescript, but SASS and css modules and I'm using the classes from css module to add them to the components, how would I adapt your code to our setup? so far I have config.module.rules.push({ test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'], include: path.resolve(__dirname, '../'), exclude: /\.module\.scss$/ }); config.module.rules.push({ test: /\.module\.scss$/, use: [ 'style-loader', { loader: 'css-loader', options: { modules: true, importLoaders: 1, localIdentName: '[path]__[name]___[local]' } }, 'sass-loader' ] }); I have SASS working, SOME css modules working (I use them as SCSS files) but if there's a SCSS module overriding a default material-ui rule (I'm using gatsby and material-ui) then the module.scss file gets overridden by the material-ui rule :( |
I pretty much used the same technique, just in an immutable way: module.exports = async ({ config }) => {
const rules = config.module.rules.map(rule => {
if (rule.test.toString() !== '/\\.css$/') {
return rule;
}
const use = rule.use.map(u => {
const { loader } = u;
if (!loader || !loader.includes('/css-loader/')) {
return u;
}
const options = {
...u.options,
modules: true
};
return {
...u,
options
};
})
return {
...rule,
use
};
})
return {
...config,
module: {
...config.module,
rules,
}
};
}; Loop over rules, find rule applied to |
@astorije |
I solved it like that in my ./storybook/main.js module.exports = {
stories: ['../stories/**/*.stories.js'],
addons: ['@storybook/addon-actions', '@storybook/addon-links'],
webpackFinal: async (config, { configType }) => {
// get index of css rule
const ruleCssIndex = config.module.rules.findIndex(rule => rule.test.toString() === '/\\.css$/');
// map over the 'use' array of the css rule and set the 'module' option to true
config.module.rules[ruleCssIndex].use.map(item => {
if (item.loader && item.loader.includes('/css-loader/')) {
item.options.modules = {
mode: 'local',
localIdentName: configType === 'PRODUCTION' ? '[local]--[hash:base64:5]' : '[name]__[local]--[hash:base64:5]',
};
}
return item;
})
// Return the altered config
return config;
}
}; |
@freesh thanks, though i did something different it helped. in my case I have been struggling for ages and I just removed all the default storybook webpack CSS stuff and used (copy/paste mostly) what Create React App gave me when I ejected, manually: module.exports = {
stories: ['../storybook/**/*.stories.tsx'],
addons: ['@storybook/addon-actions', '@storybook/addon-links'],
webpackFinal: async config => {
config.module.rules = config.module.rules.filter(rule => rule.test.toString() !== '/\\.css$/')
config.module.rules.push({oneOf: [
{ ... }
]}) also note that I know very little about webpack but running |
@freesh solution was still required for me to use Storybook outside a create react app. Thanks. I had style-loader and css-loader with typical css:modules true but it seems that the configuration is ignored in this sort of environment. I was literally only creating components in this project so the humungous create react app seemed like overkill. I don't think this should take this kind of webpack hijacking personally. It's interesting too that it appears like https://github.com/storybookjs/presets/tree/master/packages/preset-scss might provide css module too. Seems too bad that it's scss specific. I'm using css-loader modules: true without scss to keep my CSS lightweight until/unless my project absolutely needs a preprocessor (in which case postcss is most likely next thing I'd add). Lastly, I think it's also a Storybook noob thing (at least for me) since I just also encountered: which seems to perfectly tell you how to override this manually which brings me around full circle that this is not really a bug or missing feature ¯_(ツ)_/¯ but: https://storybook.js.org/docs/react/get-started/install if you see the:
It would maybe be nice to point out that Webpack can be overriden by looking at #extending-storybooks-webpack-config and a similar link to rollup if it's overridable. I think I/we are finding ourselves stubbornly trying anyway and then finding this issue :) |
Hi there webpackFinal: async (config, { configType }) => {
// `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
// You can change the configuration based on that.
// 'PRODUCTION' is used when building the static version of storybook.
const indexOfCssRules = config.module.rules.findIndex(
rule => rule.test.toString() === '/\\.css$/'
);
const indexOfModuleCssRules = config.module.rules.findIndex(
rule => rule.test.toString() === '/\\.module\\.css$/'
);
if (indexOfCssRules != -1) {
config.module.rules.splice(indexOfCssRules, 1);
}
if (indexOfModuleCssRules != -1) {
config.module.rules.splice(indexOfModuleCssRules, 1);
}
config.module.rules.push({
test: /\.css$/,
exclude: /\.module\.css$/,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: true,
}),
sideEffects: true,
include: path.resolve(__dirname, '../'),
});
config.module.rules.push({
test: /\.module\.css$/,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: true,
modules: {
localIdentName,
exportGlobals: true,
},
}),
include: path.resolve(__dirname, '../'),
});
// Return the altered config
console.log(JSON.stringify(config.module.rules));
return config;
},
|
Is your feature request related to a problem? Please describe.
I'd love to use CSS Modules together with Storybook but the default config won't let me do that out of the box.
Describe the solution you'd like
I'd like to have another loader added to the
storybookBase
webpack config which checks for/\.module.css/
and usescss-loader
with themodules
option set totrue
. At the same time/\.module.css/
must be added as exclude pattern to the default css loader config.Describe alternatives you've considered
I have added a really super ugly (and error prone) hack to filter out the css from Storybook's default webpack config and replace it with my own css loading mechanism:
https://github.com/wiremore/grid/blob/master/config/webpack.config.js/storybook.js#L7-L9
Are you able to assist bring the feature to reality?
I did, kind of. See my hack above. Feel free to adopt. If you point me to the webpack config that is used to generate the stories I could also implement it myself. It's probably not a breaking change.
Additional context
Both Gatsby and Create React App use
.module.css
to support CSS Modules without any further configuration, hacks or workarounds:Create React App
Code | Docs
Gatsby
Code | Docs
The text was updated successfully, but these errors were encountered: