-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathindex.js
107 lines (86 loc) · 3.14 KB
/
index.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
const postcss = require('postcss');
const fancyLog = require('fancy-log');
const humanSize = require('human-size');
const webpackSources = require('webpack-sources');
const pluginName = 'PostCSSAssetsPlugin';
module.exports = class PostCSSAssetsPlugin {
constructor({ test = /\.css$/, plugins = [], log = true } = {}) {
this.test = test;
this.plugins = plugins;
this.log = log ? fancyLog : () => {};
}
run(assets) {
if (Object.keys(assets).length === 0) {
return Promise.resolve();
}
this.log('PostCSSAssetsPlugin: Starting...');
return Promise.all(Object.keys(assets).reduce((result, name) => {
if (!this.test.test(name)) {
return result;
}
const asset = assets[name];
const originalCss = asset.source();
const mapName = originalCss.match(/\/\*# sourceMappingURL=(.{1,200}).*\*\/$|$/)[1];
const inlineMap = mapName ? mapName.search(/^data:/) === 0 : false;
if (inlineMap) {
this.log('PostCSSAssetsPlugin: Found inline source map');
}
const mapAsset = mapName && !inlineMap ? assets[mapName] : null;
const externalMap = mapAsset ? mapAsset.source() : undefined;
if (externalMap) {
this.log('PostCSSAssetsPlugin: Found external source map');
}
const processOptions = {
from: name,
to: name,
map: (inlineMap || externalMap) ? {
inline: inlineMap,
sourcesContent: true,
prev: externalMap,
} : false,
};
this.log(`PostCSSAssetsPlugin: Processing ${name}...`);
result.push(
postcss(this.plugins)
.process(originalCss, processOptions)
.then((postcssResult) => {
const processedCss = postcssResult.css;
const warnings = postcssResult.warnings();
if (warnings && warnings.length) {
this.log('PostCSSAssetsPlugin:', warnings.join('\n'));
}
assets[name] = new webpackSources.RawSource(processedCss);
if (mapAsset) {
assets[mapName] = new webpackSources.RawSource(JSON.stringify(postcssResult.map));
}
this.log(
'PostCSSAssetsPlugin:',
`Processed ${name}. Size before: ${humanSize(originalCss.length, 3)},`,
`size after: ${humanSize(processedCss.length, 2)}`,
);
})
.catch((error) => {
this.log('PostCSSAssetsPlugin:', `Error processing file: ${name}`, error);
throw error;
}),
);
return result;
}, []))
.then(() => {
this.log('PostCSSAssetsPlugin: Done.');
});
}
apply(compiler) {
const stage = compiler.createCompilation().constructor.PROCESS_ASSETS_STAGE_OPTIMIZE;
if (stage) {
compiler.hooks.compilation.tap(pluginName, (compilation) => {
const stageSettings = { name: pluginName, stage };
compilation.hooks.processAssets.tapPromise(stageSettings, (assets) => {
return this.run(assets || compilation.assets);
});
});
} else {
compiler.hooks.emit.tapPromise(pluginName, ({assets}) => this.run(assets));
}
}
};