# weex
# 抽取公共样式
const vueFileReg = /weex-loader/
const cssFileReg = /\.css$/
class WebpackPluginExtractCss {
constructor(options = {}) {
this.options = options
this.cssCommonModules = Object.create(null);
}
apply(compiler) {
// 编译(compilation)创建之后,执行插件
compiler.plugin('compilation', (compilation) => {
compilation.plugin('optimize-tree', (chunks, modules, cb) => {
const t1 = Date.now();
console.log('extract css start...');
// 抽取公共资源
this.processAllModules(modules);
// 开始处理资源
chunks.forEach(chunk => {
this.processChunkModules(chunk.modules);
})
const t2 = Date.now()
console.log('extract css finish in '+(t2-t1)+'ms.')
cb();
})
})
}
processAllModules(modules) {
const cssCommonModules = this.cssCommonModules;
// 抽取公共css模块
modules.forEach(module => {
if (cssFileReg.test(module.request)) {
let resource = this.getResource(module.request);
if (!cssCommonModules[resource]) {
cssCommonModules[resource] = module;
}
}
});
// 处理重复css模块
modules.forEach(module => {
// 替换css模块
if (vueFileReg.test(module.request)) {
module.dependencies.forEach(dep => {
if (dep.module && cssFileReg.test(dep.module.request)) {
let resource = this.getResource(dep.module.request);
dep.module = cssCommonModules[resource];
}
})
}
});
// 删除重复css模块
this.delRepeatModules(modules);
}
processChunkModules(modules) {
const cssCommonModules = this.cssCommonModules;
let usedModuleReqs = [];
// 替换vue文件里的公共css模块依赖
modules.forEach(module => {
if (vueFileReg.test(module.request)) {
module.dependencies.forEach(dep => {
if (dep.module && cssFileReg.test(dep.module.request)) {
let resource = this.getResource(dep.module.request);
dep.module = cssCommonModules[resource];
usedModuleReqs.push(cssCommonModules[resource].request);
}
})
}
});
// 删除重复css模块
this.delRepeatModules(modules)
// 如果chunk里不包含新的依赖,则需要引进来
usedModuleReqs = Array.from(new Set(usedModuleReqs));
this.processNewModules(modules, usedModuleReqs);
}
getResource(request) {
let elements = request.replace(/^-?!+/, "").replace(/!!+/g, "!").split("!");
return elements.pop();
}
processNewModules(modules, usedModuleReqs) {
const cssCommonModules = this.cssCommonModules;
const moduleReqs = modules.map(mod => mod.request);
usedModuleReqs.forEach(req => {
if (!moduleReqs.includes(req)) {
let resource = this.getResource(req);
modules.push(cssCommonModules[resource]);
}
});
}
delRepeatModules(modules) {
const cssCommonModules = this.cssCommonModules;
const repeatCssModules = [];
modules.forEach(module => {
Object.keys(cssCommonModules).forEach(resource => {
if (module.request.indexOf(resource) != -1 &&
module.request !== cssCommonModules[resource].request) {
repeatCssModules.push(module.request);
}
});
});
repeatCssModules.forEach(req => {
let removeIndex = modules.findIndex(module => module.request === req);
if (removeIndex != -1) {
modules.splice(removeIndex, 1);
}
})
}
}
module.exports = WebpackPluginExtractCss
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
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
← React 阿里2021第一轮笔试 →