I'd like to pass further options (like includePaths
or localIdentName
) to sass-loader/css-loader when using the new built in css modules.
Maybe hashing the css classnames via localIdentName: [hash:base64]
in production mode could be a default.
We need includePaths
because we have a monorepo and we don't want to deal with long relative paths.
I'm not part of the Next team but I've been putting some thought into the best way to handle this.
Some options:
A) Simply brute force in another option that can be used inside next.config.js
. Pass through the value to sass-loader
options
object.
Pros:
Cons:
B) Build in config detection for .sassrc.js
.sassrc.json
sass.config.js
and/or a sass
option in package.json
.
Pros:
next.config.js
Cons:
C) Build the above config detection upstream for sass-loader
.
Pros:
postcss-loader
which uses postcss-load-config
sass-loader
Cons:
sass-loader
maintainersMy personal opinion is that C is the best way forward, but maybe there's a half-step that can be taken in the meantime? I'd just like to see .sassrc.json
and such accepted out-of-box for all Webpack projects than try to shim the customization into Next.
I would go with A) since people might be used to it from the old next-plugins, e.g. https://github.com/zeit/next-plugins/blob/master/packages/next-sass/readme.md
Something like:
// next.config.js
const isProd = process.env.NODE_ENV === 'production'
module.exports = {
sassLoaderOptions: {
includePaths: ['absolute/path/a', 'absolute/path/b']
},
cssLoaderOptions: {
modules: {
// This could be a next.js default?
localIdentName: isProd ? '[hash:base64]' : '[path][name]__[local]--[hash:base64:5]',
},
}
}
As a workaround for now, you can do the following to get your custom options in there. It's not pretty but it works...
let rule, moduleRules, cssLoader, scssRules, sassLoader;
if (rule = config.module.rules.find(rule => Object.keys(rule).includes('oneOf'))) {
// Locate css-loader config for css modules
if (moduleRules = rule.oneOf.filter(r => ('test.module.scss'.match(r.test) || 'test.module.css'.match(r.test)) && Array.isArray(r.use))) {
for (const moduleRule of moduleRules) {
if (cssLoader = moduleRule.use.find(u => u.loader.match('css-loader'))) {
cssLoader.options = {
...cssLoader.options,
// Any custom css loader options here
modules: {
...cssLoader.options.modules,
// Your custom css-modules options below.
getLocalIdent: () => false, // Fall back to default getLocalIdent function
localIdentName: process.env.NODE_ENV === 'production' ? '[hash:base64:8]' : '[name]__[local]___[hash:base64:5]',
}
}
}
}
}
// Locate sass-loader config
if (scssRules = rule.oneOf.filter(r => ('test.scss'.match(r.test) || 'test.module.scss'.match(r.test)) && Array.isArray(r.use))) {
for (const scssRule of scssRules) {
if (sassLoader = scssRule.use.find(u => u.loader.match('sass-loader'))) {
sassLoader.options = {
...sassLoader.options,
// Your custom sass-loader options below.
prependData: '@import "~styles/variables.scss";',
}
}
}
}
}
Most helpful comment
I would go with A) since people might be used to it from the old next-plugins, e.g. https://github.com/zeit/next-plugins/blob/master/packages/next-sass/readme.md
Something like: