UNPKG

6.94 kBJavaScriptView Raw
1const path = require('path');
2const fs = require('fs');
3const id = 'SizePlugin';
4const table = require('table').table;
5
6//扁平化数组
7function flatten(ary){
8 var ret = [];
9 ary.map(function(el){
10 if (Array.isArray(el)) {
11 ret = ret.concat(el)
12 } else {
13 ret.push(el)
14 }
15 });
16 return ret;
17}
18
19
20function getSize(ary){
21 let defaultSize = 0;
22 ary.forEach(function(el){
23 defaultSize += el.size;
24 });
25 return defaultSize;
26}
27
28class SizePlugin {
29 apply(compiler){
30 compiler.hooks.done.tap(id, (compilation) => {
31 var map = {}, tree = {}, pages = [], Identifiers = {};
32 var assetsInfo = compilation.toJson().assets;
33
34 compilation.toJson().modules.forEach(function(module){
35
36 //过滤 node_modules 模块
37 if (/\/node_modules\//.test(module.id)) {
38 return;
39 }
40
41 let fileId = module.id.split(/\/source\//)[1];
42 // pages 和 app.js 作为业务 size 统计
43 if (/(pages|app)\/?/.test( fileId ) && /\.js$/.test(fileId) ) {
44 pages.push(fileId);
45 }
46
47 // reasons 表示 module.id 依赖宿主(被谁依赖)
48 var reasons = module.reasons
49 .map(function(el){
50 if (el.moduleId) {
51 return el.moduleId.split(/\/source\//)[1];
52 } else {
53 return '';
54 }
55 });
56 reasons = Array.from( new Set(reasons) );
57
58 // 标示哪些资源是公用的, 如果 module.id 依赖宿主为多个, 则表示该文件是公用的。
59 if (reasons.length > 1) {
60 Identifiers[fileId] = 1;
61 } else {
62 Identifiers[fileId] = 0;
63 }
64
65
66 // module.assets 表示当前资源有哪些输出文件,比如 page 页面会输出js, css, *xml
67 map[fileId] = {
68 id: fileId,
69 reasons: reasons,
70 assets: module.assets
71 }
72
73 });
74
75 //获得依赖树
76 pages.forEach(function( pagePath ){
77 for(let i in map) {
78 if (map[i].reasons.includes(pagePath)) {
79 tree[pagePath] = tree[pagePath] || [];
80 tree[pagePath].push(i);
81 if (!tree[pagePath].includes(pagePath)) {
82 tree[pagePath].push(pagePath);
83 }
84 }
85 }
86 })
87
88 //dep代表当前平台依赖哪些资源(包括公共资源),common代表该平台用到的公共资源
89 let ret = {};
90 fs.readdirSync(path.join(process.cwd(), 'source', 'pages'))
91 .filter(function(el){
92 return /^\w+/.test(el);
93 })
94 .forEach(function(plat){
95 ret[plat] = {
96 plat: plat,
97 dep: [],
98 common: []
99 }
100 })
101
102
103 for( let i in tree ) {
104 //获取单个文件打包的xml,样式, js 资源
105 let fileDeps = tree[i].map(function(dep){
106 var depAssets = map[dep].assets;
107 return depAssets.map(function(el){
108 let target = assetsInfo.find(function(item){
109 return item.name == el;
110 });
111 return {
112 name: target.name,
113 size: target.size,
114 onwer: dep
115 }
116 });
117 });
118
119 fileDeps = flatten(fileDeps);
120
121 if (!/app\.js/.test(i)) {
122 let plat = i.split('/')[1];
123 ret[plat].dep = ret[plat].dep.concat(fileDeps);
124 } else {
125 // app.js 过滤里面的 pages, react runtime 依赖, 没必要计算进去。
126 fileDeps = fileDeps.filter(function(el){
127 return !/^pages\//.test(el.name) && !/React\w+\.js$/.test(el.name)
128 });
129 ret.app = ret.app || {
130 plat: 'app',
131 dep: [].concat(fileDeps)
132 }
133 }
134
135 }
136
137 let output = [];
138 for(let plat in ret) {
139 let dep = ret[plat].dep, tem = [], commonFiles = [], files = [];
140
141 dep = dep.filter(function(el){
142 return !/React\w+\.js$/.test(el.name);
143 });
144
145 dep.forEach(function(el){
146 //公共资源
147 if (Identifiers[el.name] == 1) {
148 commonFiles.push(el);
149 }
150 //过滤 React, 防止重复计算 React size
151 if (/React\w+\.js$/.test(el.name)) {
152 if (!tem.length) {
153 tem.push(el);
154 }
155 } else {
156 files.push(el);
157 }
158 })
159
160 //一个业务线只算一个 React runtime size
161 files = files.concat(tem);
162
163 //配置 table 输出数据
164 let tableItem = [];
165 let allSize = (getSize(files)/1000).toFixed(2);
166 let commonPercent = (getSize(commonFiles)/1000).toFixed(2) / allSize;
167 commonPercent = commonPercent.toFixed(2) * 100;
168
169 tableItem.push(
170 plat,
171 Math.round( ( getSize(files)/1000).toFixed(2) ) + ' Kb',
172 commonPercent + ' %'
173 );
174
175 output.push(tableItem);
176 }
177
178 var data = [
179 ['业务平台', 'size', '公共资源占比']
180 ].concat(output)
181
182 // data = [
183 // ['0A', '0B', '0C'],
184 // ['1A', '1B', '1C'],
185 // ['2A', '2B', '2C']
186 // ];
187
188 // ╔════╤════╤════╗
189 // ║ 0A │ 0B │ 0C ║
190 // ╟────┼────┼────╢
191 // ║ 1A │ 1B │ 1C ║
192 // ╟────┼────┼────╢
193 // ║ 2A │ 2B │ 2C ║
194 // ╚════╧════╧════╝
195
196 console.log(table(data));
197
198 })
199 }
200}
201
202
203module.exports = SizePlugin;
\No newline at end of file