This repository was archived by the owner on Feb 1, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathindex.js
131 lines (114 loc) · 4.33 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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import fs from 'fs'
import Purgecss from 'purgecss'
import { ConcatSource } from 'webpack-sources'
import * as parse from './parse'
import * as search from './search'
let webpackVersion = 4
const styleExtensions = ['.css', '.scss', '.styl', '.sass', '.less']
const pluginName = 'PurgeCSS'
const purgedStats = {}
export default class PurgecssPlugin {
constructor(options) {
this.options = options
}
apply(compiler) {
if (typeof compiler.hooks === 'undefined') {
webpackVersion = 3
}
if (webpackVersion === 4) {
compiler.hooks.compilation.tap(pluginName, compilation => {
this.initializePlugin(compilation)
})
compiler.hooks.done.tapAsync(pluginName, (stats, cb) => {
this.addStats(stats)
cb()
})
} else {
compiler.plugin('this-compilation', compilation => {
this.initializePlugin(compilation)
})
compiler.plugin('done', stats => {
this.addStats(stats)
})
}
}
addStats(stats) {
if (this.options.rejected) {
stats.purged = purgedStats
}
}
initializePlugin(compilation) {
const entryPaths = parse.entryPaths(this.options.paths)
parse.flatten(entryPaths).forEach(p => {
if (!fs.existsSync(p)) throw new Error(`Path ${p} does not exist.`)
})
if (webpackVersion === 4) {
compilation.hooks.additionalAssets.tap(pluginName, () => {
this.runPluginHook(compilation, entryPaths)
})
} else {
compilation.plugin('additional-assets', callback => {
this.runPluginHook(compilation, entryPaths, callback)
})
}
}
runPluginHook(compilation, entryPaths, callback = () => {}) {
const assetsFromCompilation = search.assets(compilation.assets, ['.css'])
// Go through chunks and purge as configured
compilation.chunks.forEach(chunk => {
const { name: chunkName, files } = chunk
const assetsToPurge = assetsFromCompilation.filter(asset => {
if (this.options.only) {
return [].concat(this.options.only).some(only => asset.name.indexOf(only) >= 0)
} else {
return files.indexOf(asset.name) >= 0
}
})
assetsToPurge.forEach(({ name, asset }) => {
const filesToSearch = parse
.entries(entryPaths, chunkName)
.concat(
search.files(
chunk,
this.options.moduleExtensions || [],
file => file.resource,
webpackVersion
)
)
.filter(v => {
for (let ext of styleExtensions) {
if (v.endsWith(ext)) return false
}
return true
})
// Compile through Purgecss and attach to output.
// This loses sourcemaps should there be any!
const options = {
...this.options,
content: filesToSearch,
css: [
{
raw: asset.source()
}
]
}
if (typeof options.whitelist === 'function') {
options.whitelist = options.whitelist()
}
if (typeof options.whitelistPatterns === 'function') {
options.whitelistPatterns = options.whitelistPatterns()
}
if (typeof options.whitelistPatternsChildren === 'function') {
options.whitelistPatternsChildren = options.whitelistPatternsChildren()
}
const purgecss = new Purgecss(options)
const purged = purgecss.purge()[0]
if (purged.rejected) {
purgedStats[name] = purged.rejected
}
compilation.assets[name] = new ConcatSource(purged.css)
})
})
callback()
}
}