/
postcss.js
132 lines (105 loc) · 3.75 KB
/
postcss.js
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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.postcssOptions) {
const ident = match.loader.options.postcssOptions.ident;
const sourceMap = match.loader.options.postcssOptions.sourceMap;
match.loader.options.postcssOptions = {
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.postcssOptions) {
if (typeof match.loader.options.postcssOptions === "function") {
craPlugins = match.loader.options.postcssOptions().plugins;
} else {
craPlugins = match.loader.options.postcssOptions.plugins;
}
}
postcssPlugins = craPlugins || [];
}
if (plugins) {
postcssPlugins = typeof plugins === "function" ? plugins(postcssPlugins) : postcssPlugins.concat(plugins);
log("Added PostCSS plugins.");
}
if (match.loader.options.postcssOptions) {
match.loader.options.postcssOptions.plugins = () => postcssPlugins;
} else {
match.loader.options.postcssOptions = {
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
};