hyper-tuner-cloud/craco-less.js

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,
};