1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| const cloneDeep = require('lodash.clonedeep')
const ruleChildren = (loader) => loader.use || loader.oneOf || Array.isArray(loader.loader) && loader.loader || []
const findIndexAndRules = (rulesSource, ruleMatcher) => { let result = undefined const rules = Array.isArray(rulesSource) ? rulesSource : ruleChildren(rulesSource) rules.some((rule, index) => result = ruleMatcher(rule) ? {index, rules} : findIndexAndRules(ruleChildren(rule), ruleMatcher)) return result }
const findRule = (rulesSource, ruleMatcher) => { const {index, rules} = findIndexAndRules(rulesSource, ruleMatcher) return rules[index] }
const cssRuleMatcher = (rule) => rule.test && String(rule.test) === String(/\.css$/)
const createLoaderMatcher = (loader) => (rule) => rule.loader && rule.loader.indexOf(`/${loader}/`) !== -1 const cssLoaderMatcher = createLoaderMatcher('css-loader') const postcssLoaderMatcher = createLoaderMatcher('postcss-loader') const fileLoaderMatcher = createLoaderMatcher('file-loader')
const addAfterRule = (rulesSource, ruleMatcher, value) => { const {index, rules} = findIndexAndRules(rulesSource, ruleMatcher) rules.splice(index + 1, 0, value) }
const addBeforeRule = (rulesSource, ruleMatcher, value) => { const {index, rules} = findIndexAndRules(rulesSource, ruleMatcher) rules.splice(index, 0, value) }
module.exports = function (config, env, lessOptions = {}) { const cssRule = findRule(config.module.rules, cssRuleMatcher) const lessRule = cloneDeep(cssRule) const cssModulesRule = cloneDeep(cssRule)
cssRule.exclude = /\.module\.css$/
const cssModulesRuleCssLoader = findRule(cssModulesRule, cssLoaderMatcher) cssModulesRuleCssLoader.options = Object.assign({modules: true, localIdentName: '[local]___[hash:base64:5]'}, cssModulesRuleCssLoader.options) addBeforeRule(config.module.rules, fileLoaderMatcher, cssModulesRule)
lessRule.test = /\.less$/ lessRule.exclude = /\.module\.less$/ addAfterRule(lessRule, postcssLoaderMatcher, { 'loader': require.resolve('less-loader'), 'options': lessOptions, }) addBeforeRule(config.module.rules, fileLoaderMatcher, lessRule)
const lessModulesRule = cloneDeep(cssModulesRule) lessModulesRule.test = /\.module\.less$/ addAfterRule(lessModulesRule, postcssLoaderMatcher, require.resolve('less-loader')) addBeforeRule(config.module.rules, fileLoaderMatcher, lessModulesRule)
return config }
|