UNPKG

@craco/craco

Version:

Create React App Configuration Override, an easy and comprehensible configuration layer for create-react-app.

129 lines (101 loc) 3.44 kB
const { getLoaders, loaderByName } = require("../../../loaders"); const { log, logError } = require("../../../logger"); const { isArray, isFunction, deepMergeWithArray } = require("../../../utils"); const { projectRoot } = require("../../../paths"); const POSTCSS_MODES = { extends: "extends", file: "file" }; const CRA_PLUGINS = presetEnv => { // prettier-ignore return [ require("postcss-flexbugs-fixes"), require("postcss-preset-env")(presetEnv), require(require.resolve("postcss-normalize", { paths: [projectRoot] })) ]; }; const CRA_PRESET_ENV = { autoprefixer: { flexbox: "no-2009" }, stage: 3 }; function usePostcssConfigFile(match) { if (match.loader.options) { const ident = match.loader.options.ident; const sourceMap = match.loader.options.sourceMap; match.loader.options = { ident: ident, sourceMap: sourceMap }; log("Overwrited PostCSS config to use a config file."); } } function extendsPostcss(match, { plugins, env }) { if (isArray(plugins) || env) { let postcssPlugins; if (env) { const mergedPreset = deepMergeWithArray({}, CRA_PRESET_ENV, env); postcssPlugins = CRA_PLUGINS(mergedPreset); log("Merged PostCSS env preset."); } else { let craPlugins = []; if (match.loader.options) { craPlugins = match.loader.options.plugins(); } postcssPlugins = craPlugins || []; } if (plugins) { postcssPlugins = postcssPlugins.concat(plugins); log("Added PostCSS plugins."); } if (match.loader.options) { match.loader.options.plugins = () => postcssPlugins; } else { match.loader.options = { plugins: () => postcssPlugins }; } } } function applyLoaderOptions(match, loaderOptions, context) { if (isFunction(loaderOptions)) { match.loader.options = loaderOptions(match.loader.options || {}, context); if (!match.loader.options) { throw new Error("craco: 'style.postcss.loaderOptions' function didn't return a loader config object."); } } else { // TODO: ensure is otherwise a plain object, if not, log an error. match.loader.options = deepMergeWithArray({}, match.loader.options || {}, loaderOptions); } log("Applied PostCSS loaders options."); } function overrideLoader(match, postcssConfig, context) { const { mode, loaderOptions } = postcssConfig; if (mode === POSTCSS_MODES.file) { usePostcssConfigFile(match); } else { extendsPostcss(match, postcssConfig); } if (loaderOptions) { applyLoaderOptions(match, loaderOptions, context); } log("Overrided PostCSS loader."); } function overridePostcss(cracoConfig, webpackConfig, context) { if (cracoConfig.postcss) { const { hasFoundAny, matches } = getLoaders(webpackConfig, loaderByName("postcss-loader")); if (!hasFoundAny) { logError("Cannot find any PostCSS loaders."); return webpackConfig; } matches.forEach(x => { overrideLoader(x, cracoConfig.postcss, context); }); } return webpackConfig; } module.exports = { overridePostcss, POSTCSS_MODES };