Currently css modules are generated by using pattern: [path]---[name]---[local]---[hash:base64:5]
So example css module classname looks like:
.src-components-contact----contactBlock-module---block---JFm8l
or
.src-components-generic-image----Image-module---imageWrap---2Xy0r
All these class names are directly in html & css files and might dramatically increase bundle size.
On previous projects I've used pattern [name]_[local]--[hash:base64:5]
which excludes path to file, which in most cases is not needed. All classes are still unique because of hash.
So long css names like this (before): .src-components-generic-image----Image-module---imageWrap---2Xy0r
Will look simply like this (after): Image-module_imageWrap--2Xy0r
This might be simple change by modifying pattern in https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-1-config-css-modules/src/index.js . I might try to update code (PR) if you are fine with that.
// Might be also nice to enable configuration for developers, so that it's possible to configure to match custom needs.
馃憤 for shorter class names. However, I typically name my components like this:
/ComponentName
- index.js
- index.module.css
So your proposed pattern [name]_[local]--[hash:base64:5]
would make all my classes start with index_
, which would give shorter classnames, but not be too useful for development. Something like [folder]-[local]-[hash:base64:5]
would be better in my case.
So I guess I'd like to add a 馃憤 for this to be configurable.
Hey folks, so the reason we use the path and no short hash here is that it's actually better for gzipping, giving an overall smaller css file when minified and served. There was an investigation on it in webpack and why we went with it, as unintuitive as that might seem!
That makes sense, thanks for the quick response. I trust Gatsby to do whatever's best in production mode :)
During development I think it's useful to be able to change the default pattern, so I've made a quick plugin to allow that: https://www.npmjs.com/package/gatsby-plugin-module-local-ident-name
I trust Gatsby to do whatever's best in production mode :)
馃槃 that is maybe giving us to much credit, its good to get questions about this stuff. There are always plenty of places we miss clear optimizations
馃ぃ way too much credit
Hopefully though we're 80% of the way there but there's plenty more optimizations to be made!
Can we really get better gzip when using longer names.. hmm.. what kind of magic it is 馃槂but I believe you that probably we can get similar size with and without paths, but still there are more things to consider..
Downsides of current approach:
Why to keep current approach:
Maybe a simpler solution would be to make the LOCAL_IDENT_NAME
a configurable option in gatsby-config.js
using the same webpack replacement syntax
I've created PR with node environment variable (CSS_MODULES_LOCAL_IDENT_NAME
) https://github.com/gatsbyjs/gatsby/pull/3411
It's working, tested by copying file to project (not sure why it doesn't work with gatsby-dev - probably because config is dependency of plugin).
But please check if this might be solution you are comfortable with. If yes, then would be good to add it somewhere to documentation - maybe to custom webpack config section.
I've made a plugin to do this, see:
https://github.com/m-allanson/gatsby-plugin-module-local-ident-name
https://www.npmjs.com/package/gatsby-plugin-module-local-ident-name
It only works for gatsby develop
at the moment as that suits my needs. I'm happy to add anyone as a collaborator if they'd like to expand on it.
@m-allanson looks interesting 馃憤 but to be complete I think would be nice to have option to configure also production build... shouldn't it be issue? What do you think..
@jurosh yeah I agree, a good idea and should be pretty easy to add.
I know about this article that explains how to aggressively minify CSS Modules class names, but I don't know how to implement the solution described in Gatsby 馃槩 https://medium.freecodecamp.org/reducing-css-bundle-size-70-by-cutting-the-class-names-and-using-scope-isolation-625440de600b
I'm having a hard time believing that longer class names can produce a smaller compressed bundle than if these class names were minified to begin with... The guy in the article says that:
The first argument against such minification is that the compression algorithms will do it for you. GO2CINEMA [the website being optimized] CSS bundle compressed using the Brotli algorithm saves a mere 1 KB compared to the original bundle with the long class names. [and minifying his class names reduced the bundle size from 140Kb to 47Kb, which is a more significant than the 1Kb reduction achieved by compressing long class names with Brotli]
@jquense, are you sure longer class names really produce a smaller bundle? 馃槙
And does anyone know how to implement the solution described in the article with Gatsby? Thanks! 馃檪
Gzip is magic :-) http://www.infinitepartitions.com/art001.html
Then no need to bother?
Yeah, I wouldn't mind a PR adding support for what he did as long as it doesn't increasing processing time but I think there's a long list of other more important improvements we could make to Gatsby.
That being said, open source is all about scratching your own itch so if this is what floats your boat, by all means do it :-)
It wouldn't hurt anyone to save 500 bytes!
But didn't you say minifying the class names will make the bundle bigger?! I'm a little confused... 馃槙
No it'll make the bundle smaller but it's a very small difference e.g. ~1%
Happy to take a PR adding support for minified class names if the it also demonstrates that it won't increase build times any but closing this issue now.
I just looked into it and also think this could be an area of improvement. Shorter names for development like provided with https://github.com/m-allanson/gatsby-plugin-module-local-ident-name and thoughtfully minified class names as described here: https://medium.freecodecamp.org/reducing-css-bundle-size-70-by-cutting-the-class-names-and-using-scope-isolation-625440de600b.
Are there any updates on this? If not, maybe I can find the time to make an PR to Gatsby.
@KyleAMathews It shouldn't increase build time for development but if it lowers the size of production bundles, a slower gatsby build
would be acceptable, I think. 馃槍
gatsby-node.js
const replacePath = (str) => str.replace('[path]---[name]---[local]---[hash:base64:5]', '[local]-[hash:base64:5]');
const modules = ['sassModules', 'cssModules'];
exports.modifyWebpackConfig = ({ config, stage }) => {
switch (stage) {
case 'develop':
modules.map((item) => {
config.loader(item, (current) => {
current.loaders = current.loaders.map((item) => {
return replacePath(item);
});
return current;
});
});
break;
case 'build-css':
case 'build-html':
case 'build-javascript':
modules.map((item) => {
config.loader(item, (current) => {
current.loader = replacePath(current.loader);
return current;
});
});
break;
}
return config;
};
// in gatsby-config.js
plugins: [
{
resolve: `gatsby-plugin-sass`,
options: {
cssLoaderOptions: {
localIdentName: '[local]--[hash:base64:5]'
},
},
},
]
// in gatsby-config.js plugins: [ { resolve: `gatsby-plugin-sass`, options: { cssLoaderOptions: { localIdentName: '[local]--[hash:base64:5]' }, }, }, ]
I tried this out, but nothing changed. Tried debugging it until I eventually realized I needed to upgrade my gatsby-plugin-sass
. So, this is a heads up to everyone else: You might need to upgrade your gatsby-plugin-sass
!
Applying cssLoaderOptions
is only possible since https://github.com/gatsbyjs/gatsby/pull/9462
In case somebody still needing a solution just install this plugin: https://github.com/stldo/gatsby-plugin-minify-classnames
It Is working with Gatsby v2
Most helpful comment
Maybe a simpler solution would be to make the
LOCAL_IDENT_NAME
a configurable option ingatsby-config.js
using the same webpack replacement syntax