-
-
Save elado/5891c94c1072cb9f18749761131a7a36 to your computer and use it in GitHub Desktop.
Next.js LESS CSS support (for AntD)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { cloneDeep } = require('lodash'); | |
// this plugin finds next.js's sass rules and duplicates them with less | |
// it mimics the exact behavior of CSS extraction/modules/client/server of SASS | |
// tested on next 10.1.3 with webpack5 | |
function withLess(nextConfig) { | |
return Object.assign({}, nextConfig, { | |
webpack(config, opts) { | |
// there are 2 relevant sass rules in next.js - css modules and global css | |
let sassModuleRule; | |
// global sass rule (does not exist in server builds) | |
let sassGlobalRule; | |
const cssRule = config.module.rules.find((rule) => rule.oneOf?.[0]?.options?.__next_css_remove); | |
const addLessToRegExp = (rx) => new RegExp(rx.source.replace('|sass', '|sass|less'), rx.flags); | |
const addLessToRuleTest = (test) => { | |
if (Array.isArray(test)) { | |
return test.map((rx) => addLessToRegExp(rx)); | |
} else { | |
return addLessToRegExp(test); | |
} | |
}; | |
cssRule.oneOf.forEach((rule, i) => { | |
if (rule.options?.__next_css_remove) return; | |
if (rule.use?.loader === 'error-loader') { | |
rule.test = addLessToRuleTest(rule.test); | |
} else if (rule.use?.loader?.includes('file-loader')) { | |
rule.issuer = addLessToRuleTest(rule.issuer); | |
} else if (rule.use?.includes?.('ignore-loader')) { | |
rule.test = addLessToRuleTest(rule.test); | |
} else if (rule.test?.source === '\\.module\\.(scss|sass)$') { | |
sassModuleRule = rule; | |
} else if (rule.test?.source === '(?<!\\.module)\\.(scss|sass)$') { | |
sassGlobalRule = rule; | |
} | |
}); | |
const lessLoader = { | |
loader: 'less-loader', | |
options: { | |
lessOptions: { | |
javascriptEnabled: true, | |
}, | |
}, | |
}; | |
let lessModuleRule = cloneDeep(sassModuleRule); | |
const configureLessRule = (rule) => { | |
rule.test = new RegExp(rule.test.source.replace('(scss|sass)', 'less')); | |
// replace sass-loader (last entry) with less-loader | |
rule.use.splice(-1, 1, lessLoader); | |
}; | |
configureLessRule(lessModuleRule); | |
cssRule.oneOf.splice(cssRule.oneOf.indexOf(sassModuleRule) + 1, 0, lessModuleRule); | |
if (sassGlobalRule) { | |
let lessGlobalRule = cloneDeep(sassGlobalRule); | |
configureLessRule(lessGlobalRule); | |
cssRule.oneOf.splice(cssRule.oneOf.indexOf(sassGlobalRule) + 1, 0, lessGlobalRule); | |
} | |
if (typeof nextConfig.webpack === 'function') { | |
return nextConfig.webpack(config, opts); | |
} | |
return config; | |
}, | |
}); | |
} | |
module.exports = withLess; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment