-
Notifications
You must be signed in to change notification settings - Fork 8
/
gulpfile.js
288 lines (247 loc) · 9.73 KB
/
gulpfile.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
//在gulpfile中先载入gulp包,因为这个包提供了一些API
const gulp = require('gulp');
const babel = require('gulp-babel');
const plumber = require('gulp-plumber');
const babelCore = require("@babel/core");
const utf8Convert = require('gulp-utf8-convert');
const uglify = require('gulp-uglify');
const header = require('gulp-header');
const htmlmin = require('gulp-htmlmin');
const cheerio = require('gulp-cheerio');
const cssmin = require('gulp-clean-css');
const obfuscator = require('javascript-obfuscator');
const obfuscatorGulp = require('./gulp-javascript-obfuscator.js');
const fs = require('fs');
const path = require('path');
//////////////////////////以下参数可以根据实际情况调整/////////////////////
const copyright = "版权所有 火星科技 http://marsgis.cn";
//这个时间后修改的文件不处理(增量更新时使用)
var lastTime;
//排除不拷贝的文件类型后缀
const noCopyFileType = [".psd", ".doc", ".docx", ".txt", ".md", ".zip", ".rar"];
//定义不做压缩混淆直接拷贝的目录
const noPipePathDef = [
'\\Cesium\\'
];
//排除不拷贝的目录
const noCopyPathDef = [
'\\.svn',
'\\.git',
'\\.vscode',
'\\node_modules\\',
"\\CesiumUnminified\\",
"-src.",//排除-src的文件
];
////////////////////自定义设置////////////////////
//需要压缩混淆的根目录
var srcPath = 'src';
//生成到的目标目录
var distPath = 'dist';
var noPipePath = [];
var noCopyPath = [];
// lastTime = new Date("2020-08-01 08:00:00")
////////////////////压缩混淆////////////////////
//js高级混淆的参数,更多参数参考: https://github.com/javascript-obfuscator/javascript-obfuscator
var optsObfuscator = {
rotateUnicodeArray: true,
compact: true
}
const fileList = [];
gulp.task('build', done => {
// console.log('--------代码编译开始--------');
console.log('开始处理目录:' + srcPath);
console.log('生成至目录:' + distPath);
travel(srcPath);
fileList.forEach(t => {
var srcFile = t.pathname;
const outFilePath = distPath;
// console.log('读取:' + srcFile + '\n输出:' + outFilePath + '\n');
let stat = fs.statSync(srcFile);
if (lastTime != null && stat.mtime < lastTime) {
return;
}
let bannerData = { date: stat.mtime.format("yyyy-M-d HH:mm:ss") };
let banner = '/* <%= date %> | ' + copyright + ' */\n';
let bannerHtml = '<!-- <%= date %> | ' + copyright + ' -->\n';
switch (t.fileType) {
case '.js':
if (stat.size > 102400) {
optsObfuscator.controlFlowFlattening = false //大文件不建议为true,造成文件更大
}
else {
optsObfuscator.controlFlowFlattening = true
}
gulp.src(srcFile, {
base: srcPath
})
.pipe(plumber({
errorHandler: function (err) {
throwOnlyCopy(srcPath, srcFile, outFilePath, err);
}
}))
.pipe(utf8Convert({
encNotMatchHandle: function (file) {
throwOnlyCopy(srcPath, srcFile, outFilePath, " 编码可能不是utf-8,避免乱码请检查!");
}
}))
.pipe(babel({
presets: ['@babel/preset-env'],
sourceType: "script",
compact: false
}))
.pipe(uglify().on('error', function () {
this.emit('end');
throwOnlyCopy(srcPath, srcFile, outFilePath, err);
}))
.pipe(optsObfuscator.compact ? obfuscatorGulp(optsObfuscator) : header(banner, bannerData))
.pipe(header(banner, bannerData))
.pipe(gulp.dest(outFilePath))
break
case ".html":
gulp.src(srcFile, {
base: srcPath
}).pipe(plumber({
errorHandler: function (err) {
throwOnlyCopy(srcPath, srcFile, outFilePath, err);
}
}))
.pipe(utf8Convert({
encNotMatchHandle: function (file) {
throwOnlyCopy(srcPath, srcFile, outFilePath, " 编码可能不是utf-8,避免乱码请检查!");
}
}))
.pipe(cheerio({
run: function ($, file) {
$('script').each(function () { // html内联js编译
const script = $(this);
try {
if (!script.attr('src')) {
const scriptHtml = script.html();
const result = babelCore.transformSync(scriptHtml, {
presets: ['@babel/preset-env'],
sourceType: "script",
compact: false
});
if (optsObfuscator.compact) {
//高级加密
optsObfuscator.controlFlowFlattening = true
var obfuscationResult = obfuscator.obfuscate(result.code, optsObfuscator);
script.text(obfuscationResult.getObfuscatedCode());
}
else {
//普通加密
script.text(result.code);
}
}
} catch (err) {
console.log("转换html出错了",err);
throwOnlyCopy(srcPath, srcFile, outFilePath, "html内联js编译错误!");
}
});
}
}))
.pipe(htmlmin({
collapseWhitespace: true, //清除空格,压缩html,作用比较大,引起的改变压缩量也特别大
collapseBooleanAttributes: true, //省略布尔属性的值,比如:<input checked="checked"/>,那么设置这个属性后,就会变成 <input checked/>
removeComments: true, //清除html中注释
removeEmptyAttributes: true, //清除所有的空属性
removeScriptTypeAttributes: true, //清除所有script标签中的type="text/javascript"属性
removeStyleLinkTypeAttributes: true, //清楚所有Link标签上的type属性
minifyJS: true, //压缩html中的javascript代码
minifyCSS: true //压缩html中的css代码
}))
.pipe(header(bannerHtml, bannerData))
.pipe(gulp.dest(outFilePath));
break;
case ".css":
gulp.src(srcFile, {
base: srcPath
})
.pipe(plumber({
errorHandler: function (err) {
throwOnlyCopy(srcPath, srcFile, outFilePath, err);
}
}))
.pipe(utf8Convert({
encNotMatchHandle: function (file) {
throwOnlyCopy(srcPath, srcFile, outFilePath, " 编码可能不是utf-8,避免乱码请检查!");
}
}))
.pipe(cssmin({
advanced: false, //类型:Boolean 默认:true [是否开启高级优化(合并选择器等)]
compatibility: 'ie8', //保留ie7及以下兼容写法 类型:String 默认:''or'*' [启用兼容模式; 'ie7':IE7兼容模式,'ie8':IE8兼容模式,'*':IE9+兼容模式]
keepSpecialComments: '*' //保留所有特殊前缀 当你用autoprefixer生成的浏览器前缀,如果不加这个参数,有可能将会删除你的部分前缀
}))
.pipe(header(banner, bannerData))
.pipe(gulp.dest(outFilePath));
break;
default:
gulp.src(srcFile, {
base: srcPath
}).pipe(gulp.dest(outFilePath));
break;
}
})
done();
// console.log('--------代码编译完成--------');
});
//遍历目录获取文件列表
function travel(dir) {
fs.readdirSync(dir).forEach(function (file) {
let pathname = path.join(dir, file);
if (fs.statSync(pathname).isDirectory()) {
//排除不拷贝的目录,文件不会生成到目标目录中
if (noCopyPathDef.some(t => pathname.indexOf(t) !== -1)) return;
if (noCopyPath.some(t => pathname.indexOf(t) !== -1)) return;
travel(pathname);
} else {
let fileType = path.parse(pathname).ext;
// console.log(pathname);
//排除不拷贝的文件,文件不会生成到目标目录中
if (noCopyPathDef.some(t => pathname.indexOf(t) !== -1)) return;
if (noCopyPath.some(t => pathname.indexOf(t) !== -1)) return;
if (noCopyFileType.indexOf(fileType) !== -1) return;
//不做压缩处理,直接原样拷贝过去
if (noPipePath.some(t => pathname.indexOf("\\Cesium\\") !== -1)//不对Cesium目录压缩
|| noPipePathDef.some(t => pathname.indexOf(t) !== -1)
|| noPipePath.some(t => pathname.indexOf(t) !== -1)
) {
fileType = "";
}
fileList.push({
pathname,
fileType
})
}
});
}
// 抛出错误信息,直接copy文件,不影响整个混淆流程
function throwOnlyCopy(srcPath, pathname, outFilePath, message) {
console.log(`警告:该文件转换异常,未混淆成功,将直接拷贝过去 ${pathname}`, message);
if (pathname && outFilePath) {
gulp.src(pathname, {
base: srcPath
}).pipe(gulp.dest(outFilePath));
}
}
Date.prototype.format = function (fmt) {
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours() % 12 == 0 ? 12 : this.getHours() % 12, //小时
"H+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
}
for (var k in o) {
if (new RegExp("(" + k + ")").test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
}
}
return fmt;
};