141 lines
3.8 KiB
JavaScript
141 lines
3.8 KiB
JavaScript
const path = require('path');
|
|
const { getLoader, loaderByName, throwUnexpectedConfigError } = require('@craco/craco');
|
|
|
|
const overrideWebpackConfig = ({ context, webpackConfig, pluginOptions }) => {
|
|
const throwError = (message, githubIssueQuery) =>
|
|
throwUnexpectedConfigError({
|
|
packageName: 'craco-less',
|
|
githubRepo: 'DocSpring/craco-less',
|
|
message,
|
|
githubIssueQuery,
|
|
});
|
|
|
|
const lessExtension = /\.less$/;
|
|
const options = pluginOptions || {};
|
|
const pathSep = path.sep;
|
|
|
|
const oneOfRule = webpackConfig.module.rules.find(rule => rule.oneOf);
|
|
if (!oneOfRule) {
|
|
throwError(
|
|
'Can\'t find a \'oneOf\' rule under module.rules in the ' +
|
|
`${context.env} webpack config!`,
|
|
'webpack+rules+oneOf',
|
|
);
|
|
}
|
|
|
|
const sassRule = oneOfRule.oneOf.find(
|
|
rule => rule.test && rule.test.toString().includes('scss|sass'),
|
|
);
|
|
if (!sassRule) {
|
|
throwError(
|
|
'Can\'t find the webpack rule to match scss/sass files in the ' +
|
|
`${context.env} webpack config!`,
|
|
'webpack+rules+scss+sass',
|
|
);
|
|
}
|
|
let lessRule = {
|
|
exclude: /\.module\.(less)$/,
|
|
test: lessExtension,
|
|
use: [],
|
|
};
|
|
|
|
const loaders = sassRule.use;
|
|
loaders.forEach(ruleOrLoader => {
|
|
let rule;
|
|
if (typeof ruleOrLoader === 'string') {
|
|
rule = {
|
|
loader: ruleOrLoader,
|
|
options: {},
|
|
};
|
|
} else {
|
|
rule = ruleOrLoader;
|
|
}
|
|
|
|
if (
|
|
(context.env === 'development' || context.env === 'test') &&
|
|
rule.loader.includes(`${pathSep}style-loader${pathSep}`)
|
|
) {
|
|
lessRule.use.push({
|
|
loader: rule.loader,
|
|
options: {
|
|
...rule.options,
|
|
...(options.styleLoaderOptions || {}),
|
|
},
|
|
});
|
|
} else if (rule.loader.includes(`${pathSep}css-loader${pathSep}`)) {
|
|
lessRule.use.push({
|
|
loader: rule.loader,
|
|
options: {
|
|
...rule.options,
|
|
...(options.cssLoaderOptions || {}),
|
|
},
|
|
});
|
|
} else if (rule.loader.includes(`${pathSep}postcss-loader${pathSep}`)) {
|
|
lessRule.use.push({
|
|
loader: rule.loader,
|
|
options: {
|
|
...rule.options,
|
|
...(options.postcssLoaderOptions || {}),
|
|
},
|
|
});
|
|
} else if (rule.loader.includes(`${pathSep}resolve-url-loader${pathSep}`)) {
|
|
lessRule.use.push({
|
|
loader: rule.loader,
|
|
options: {
|
|
...rule.options,
|
|
...(options.resolveUrlLoaderOptions || {}),
|
|
},
|
|
});
|
|
} else if (
|
|
context.env === 'production' &&
|
|
rule.loader.includes(`${pathSep}mini-css-extract-plugin${pathSep}`)
|
|
) {
|
|
lessRule.use.push({
|
|
loader: rule.loader,
|
|
options: {
|
|
...rule.options,
|
|
...(options.miniCssExtractPluginOptions || {}),
|
|
},
|
|
});
|
|
} else if (rule.loader.includes(`${pathSep}sass-loader${pathSep}`)) {
|
|
const defaultLessLoaderOptions =
|
|
context.env === 'production' ? { sourceMap: true } : {};
|
|
lessRule.use.push({
|
|
loader: require.resolve('less-loader'),
|
|
options: {
|
|
...defaultLessLoaderOptions,
|
|
...options.lessLoaderOptions,
|
|
},
|
|
});
|
|
} else {
|
|
throwError(
|
|
`Found an unhandled loader in the ${context.env} webpack config: ${rule.loader}`,
|
|
'webpack+unknown+rule',
|
|
);
|
|
}
|
|
});
|
|
|
|
if (options.modifyLessRule) {
|
|
lessRule = options.modifyLessRule(lessRule, context);
|
|
}
|
|
oneOfRule.oneOf.push(lessRule);
|
|
|
|
const { isFound, match: fileLoaderMatch } = getLoader(
|
|
webpackConfig,
|
|
loaderByName('file-loader'),
|
|
);
|
|
if (!isFound) {
|
|
throwError(
|
|
`Can't find file-loader in the ${context.env} webpack config!`,
|
|
'webpack+file-loader',
|
|
);
|
|
}
|
|
fileLoaderMatch.loader.exclude.push(lessExtension);
|
|
|
|
return webpackConfig;
|
|
};
|
|
|
|
module.exports = {
|
|
overrideWebpackConfig,
|
|
};
|