1 | Array.prototype.unique = function () {
|
2 | var res = [];
|
3 | var json = {};
|
4 | for (var i = 0; i < this.length; i++) {
|
5 | if (!json[this[i]]) {
|
6 | res.push(this[i]);
|
7 | json[this[i]] = 1;
|
8 | }
|
9 | }
|
10 | return res;
|
11 | }
|
12 |
|
13 | module.exports = function(env, port, hbconfig, wpconfig) {
|
14 | var gulp = require('gulp');
|
15 | var gulpif = require('gulp-if');
|
16 | var inlinesource = require('gulp-inline-source');
|
17 | var htmlmin = require('gulp-minify-html');
|
18 | var base64 = require('gulp-base64');
|
19 | var count = require('gulp-file-count');
|
20 | var del = require('del');
|
21 |
|
22 |
|
23 | var handleServer = require('./functions/server.js');
|
24 | var handleWatch = require('./functions/watch.js');
|
25 | var handleJS = require('./functions/handleJS.js');
|
26 | var handleCSS = require('./functions/handleCSS.js');
|
27 | var handleImage = require('./functions/handleImage.js');
|
28 | var handleCount = require('./functions/handleCount.js');
|
29 |
|
30 | var through = require('through2');
|
31 | var cheerio = require('cheerio');
|
32 | var path = require('path');
|
33 | var fs = require('fs-extra');
|
34 | var process = require('process');
|
35 | var is = require('is_js');
|
36 |
|
37 | var logger = require('./utils/logger.js');
|
38 | var isIgnore = require('./utils/isIgnore.js');
|
39 | var isUrl = require('./utils/isUrl.js');
|
40 | var gulpFileCount = require('./utils/gulpFileCount.js');
|
41 |
|
42 | var currentPath = process.cwd();
|
43 |
|
44 | var getAbsolutePath = function(origin, extra) {
|
45 | if (!origin) {
|
46 | return;
|
47 | }
|
48 | if (!extra) {
|
49 | var extra = '';
|
50 | }
|
51 | if (is.string(origin)) {
|
52 | origin = path.join(currentPath, origin, extra);
|
53 | }
|
54 | else if (is.array(origin)) {
|
55 | origin.forEach(function(item, i) {
|
56 | origin[i] = path.join(currentPath, item, extra);
|
57 | })
|
58 | }
|
59 | }
|
60 |
|
61 | |
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 | try {
|
70 | var config = hbconfig || require(path.join(currentPath, './html-bundler.config'));
|
71 | } catch(e) {
|
72 | logger.error('html-bundler.config.js 配置文件出现错误');
|
73 | return
|
74 | }
|
75 |
|
76 | if (!wpconfig && !fs.existsSync(path.join(currentPath, './webpack.config.js'))) {
|
77 | logger.info('当前目录下没有webpack.config.js文件 ,将使用默认配置,如果需要自定义,请使用`hb init -w`命令进行创建。');
|
78 | }
|
79 |
|
80 | |
81 |
|
82 |
|
83 | var conf = {};
|
84 |
|
85 | var options = [
|
86 | 'entries',
|
87 | 'output',
|
88 | 'minify',
|
89 | 'minifyHTML',
|
90 | 'bundle',
|
91 | 'sourcemap',
|
92 | 'concat',
|
93 | 'less',
|
94 | 'inline',
|
95 | 'server',
|
96 | 'custom',
|
97 | 'codeCount',
|
98 | 'watchFolder',
|
99 | 'imgFolder',
|
100 | 'define',
|
101 | 'buildTarget'];
|
102 |
|
103 | options.forEach(function(item) {
|
104 | conf[item] = config[env + 'Mod'][item];
|
105 | })
|
106 |
|
107 | |
108 |
|
109 |
|
110 | var defaultBuildTarget = {
|
111 | js: './js/',
|
112 | css: './css/',
|
113 | imgs: './images/',
|
114 | html: './html/'
|
115 | };
|
116 |
|
117 | if (!conf.buildTarget || conf.buildTarget === 'default') {
|
118 | conf.buildTarget = defaultBuildTarget;
|
119 | }
|
120 | else if (is.object(conf.buildTarget)) {
|
121 | conf.buildTarget.js = conf.buildTarget.js || './js/';
|
122 | conf.buildTarget.css = conf.buildTarget.css || './css/';
|
123 | conf.buildTarget.imgs = conf.buildTarget.imgs || './images/';
|
124 | conf.buildTarget.html = conf.buildTarget.html || './html/';
|
125 | }
|
126 | else if (conf.buildTarget === 'same') {
|
127 | conf.buildTarget = {
|
128 | js: '',
|
129 | css: '',
|
130 | imgs: '',
|
131 | html: ''
|
132 | }
|
133 | }
|
134 |
|
135 |
|
136 | conf.src = path.join(currentPath, config.src);
|
137 | conf.output = path.join(currentPath, conf.output);
|
138 | config.imgFolder && (conf.imgSrc = path.join(currentPath, config.imgFolder, './**'));
|
139 |
|
140 | if (conf.entries) {
|
141 | getAbsolutePath(conf.entries);
|
142 | }
|
143 | getAbsolutePath(config.entries);
|
144 | getAbsolutePath(config.moveList);
|
145 |
|
146 |
|
147 | |
148 |
|
149 |
|
150 | if (is.object(conf.watchFolder)) {
|
151 | getAbsolutePath(conf.watchFolder.css, '**');
|
152 | getAbsolutePath(conf.watchFolder.js, '**');
|
153 | getAbsolutePath(conf.watchFolder.imgs, '**');
|
154 | getAbsolutePath(conf.watchFolder.html, '**');
|
155 | }
|
156 |
|
157 | |
158 |
|
159 |
|
160 | var addInlineAttr = function() {
|
161 | return through.obj(function (file, enc, cb) {
|
162 | if (file.isNull()) {
|
163 | this.push(file);
|
164 | return cb();
|
165 | }
|
166 |
|
167 | if (file.isStream()) {
|
168 | return cb();
|
169 | }
|
170 |
|
171 | var content = file.contents.toString();
|
172 | var $ = cheerio.load(content, {xmlMode: false, decodeEntities: false});
|
173 |
|
174 | $('script').each(function(i, item) {
|
175 | var src = $(item).attr('src');
|
176 | if (!isUrl(src)) {
|
177 | $(item).attr('inline', 'inline');
|
178 | }
|
179 | });
|
180 | $('link').each(function(i, item) {
|
181 | var href = $(item).attr('href');
|
182 | if (!isUrl(href)) {
|
183 | $(item).attr('inline', 'inline');
|
184 | }
|
185 | });
|
186 | $('img').attr('inline', 'inline');
|
187 |
|
188 | file.contents = new Buffer($.html());
|
189 | this.push(file);
|
190 | cb();
|
191 | });
|
192 | }
|
193 |
|
194 | |
195 |
|
196 |
|
197 | var findResource = function(handleLimit) {
|
198 | return through.obj(function (file, enc, cb) {
|
199 | if (file.isNull()) {
|
200 | this.push(file);
|
201 | return cb();
|
202 | }
|
203 |
|
204 | if (file.isStream()) {
|
205 | return cb();
|
206 | }
|
207 |
|
208 | var jsArr = [];
|
209 | var cssArr = [];
|
210 | var imgArr = [];
|
211 | var ignoreArr = [];
|
212 | var content = file.contents.toString();
|
213 | var $ = cheerio.load(content);
|
214 | var filename = file.path.replace(file.base, '').replace('.html', '');
|
215 | var cwd = file.cwd;
|
216 |
|
217 | |
218 |
|
219 |
|
220 | var getPath = function(item, arr, attr) {
|
221 | var originPath = item.attr(attr);
|
222 | if (is.string(originPath) && !isUrl(originPath)) {
|
223 | var htmlPath = path.dirname(file.path);
|
224 | var result = path.join(htmlPath, originPath);
|
225 | if (!isIgnore(result, config.ignore)) {
|
226 | arr.push(result);
|
227 | }
|
228 | else {
|
229 | ignoreArr.push(result);
|
230 | }
|
231 | }
|
232 | }
|
233 |
|
234 | $('script').each(function(i, item) {
|
235 | getPath($(item), jsArr, 'src');
|
236 | })
|
237 |
|
238 | $('link').each(function(i, item) {
|
239 | getPath($(item), cssArr, 'href');
|
240 | })
|
241 |
|
242 | $('img').each(function(i, item) {
|
243 | getPath($(item), imgArr, 'src');
|
244 | });
|
245 |
|
246 | |
247 |
|
248 |
|
249 | imgArr.unique();
|
250 | cssArr.unique();
|
251 | jsArr.unique();
|
252 | ignoreArr.unique();
|
253 |
|
254 |
|
255 | var replaceResource = function(type) {
|
256 | var htmlDir = path.relative(file.base, path.dirname(file.path));
|
257 | var htmlOutput = path.join(conf.output, conf.buildTarget.html, htmlDir);
|
258 | var jsOutput = path.join(conf.output, conf.buildTarget.js);
|
259 | var cssOutput = path.join(conf.output, conf.buildTarget.css);
|
260 | var imgsOutput = path.join(conf.output, conf.buildTarget.imgs);
|
261 | var timeStamp = new Date().getTime();
|
262 | var jsPath = path.join(path.relative(htmlOutput, jsOutput), filename +'.js') + '?v=' + timeStamp;
|
263 | var cssPath = path.join(path.relative(htmlOutput, cssOutput), filename +'.css') + '?v=' + timeStamp;;
|
264 | if (type !== 'css') {
|
265 | var JSAppended = false;
|
266 | $('script').each(function(i, item) {
|
267 | var src = $(item).attr('src');
|
268 | var parent = $(item).parent();
|
269 | $(item).remove();
|
270 | if (src && !isUrl(src) && !isIgnore(path.join(file.base, src), config.ignore)) {
|
271 | if (!JSAppended) {
|
272 | parent.append('<script type="text/javascript" src="' + jsPath + '"></script>');
|
273 | JSAppended = true;
|
274 | }
|
275 | }
|
276 | else {
|
277 | parent.append($(item));
|
278 | }
|
279 | });
|
280 | }
|
281 |
|
282 | if (type !== 'js') {
|
283 | var CSSAppended = false;
|
284 | $('link').each(function(i, item) {
|
285 | var href = $(item).attr('href');
|
286 | var parent = $(item).parent();
|
287 | $(item).remove();
|
288 | if (href && !isUrl(href) && !isIgnore(path.join(file.base, href), config.ignore)) {
|
289 | if (!CSSAppended) {
|
290 | parent.append('<link rel="stylesheet" type="text/css" href="' + cssPath + '"/>');
|
291 | CSSAppended = true
|
292 | }
|
293 | }
|
294 | else {
|
295 | parent.append($(item));
|
296 | }
|
297 | });
|
298 | }
|
299 | }
|
300 |
|
301 | var addVersion = function(type) {
|
302 | if (type !== 'css') {
|
303 | $('script').each(function(i, item) {
|
304 | var src = $(this).attr('src')
|
305 | if (src) {
|
306 | var origin = src.replace(/.\w+$/g, '.js');
|
307 | $(this).attr('src', origin + '?v=' + new Date().getTime());
|
308 | }
|
309 |
|
310 | })
|
311 | }
|
312 |
|
313 | if (type !== 'js') {
|
314 | $('link').each(function(i, item) {
|
315 | var href = $(this).attr('href');
|
316 | if (href) {
|
317 | var origin = href.replace(/.\w+$/g, '.css');
|
318 | $(this).attr('href', origin + '?v=' + new Date().getTime());
|
319 | }
|
320 | })
|
321 | }
|
322 | }
|
323 |
|
324 | if (conf.concat) {
|
325 | replaceResource();
|
326 | }
|
327 | else if (conf.bundle) {
|
328 | replaceResource('js');
|
329 | addVersion('css');
|
330 | }
|
331 | else {
|
332 | addVersion();
|
333 | }
|
334 |
|
335 | if (handleLimit === 'js') {
|
336 | handleJS(jsArr, conf, filename, env, wpconfig);
|
337 | }
|
338 | else if (handleLimit === 'css') {
|
339 | handleCSS(cssArr, conf, filename, env);
|
340 | }
|
341 | else if (handleLimit === 'imgs') {
|
342 | handleImage(imgArr, conf, filename, env);
|
343 | }
|
344 | else {
|
345 | handleJS(jsArr, conf, filename, env, wpconfig);
|
346 | handleCSS(cssArr, conf, filename, env);
|
347 | handleImage(imgArr, conf, filename, env);
|
348 | }
|
349 |
|
350 | |
351 |
|
352 |
|
353 | if (ignoreArr.length) {
|
354 | gulp.src(ignoreArr)
|
355 | .pipe(gulp.dest(function(file){
|
356 | return path.dirname(path.join(conf.output, path.relative(conf.src, file.path)));
|
357 | }));
|
358 | }
|
359 |
|
360 | file.contents = new Buffer($.html({xmlMode: false, decodeEntities: false}));
|
361 | this.push(file);
|
362 |
|
363 | cb();
|
364 | });
|
365 |
|
366 | }
|
367 |
|
368 | var run = function(env) {
|
369 | logger.info('build begin!!');
|
370 | var getTarget = function(type) {
|
371 | if (!conf.buildTarget[type]){
|
372 | var target = function(file){
|
373 | return path.dirname(path.join(conf.output, path.relative(conf.src, file.path)));
|
374 | }
|
375 | }
|
376 | else {
|
377 | var target = path.join(conf.output, conf.buildTarget[type]);
|
378 | }
|
379 | return target;
|
380 | }
|
381 |
|
382 | var htmlTarget = getTarget('html');
|
383 | var imageTarget = getTarget('imgs');
|
384 |
|
385 | var promise = new Promise((resolve, reject) => {
|
386 | if (env !== 'js' && env !== 'css') {
|
387 | if (conf.imgSrc) {
|
388 | logger.notice('执行图片复制');
|
389 | gulp.src(conf.imgSrc)
|
390 | .on('error', reject)
|
391 | .pipe(gulp.dest(imageTarget))
|
392 | .on('end', resolve)
|
393 | }
|
394 | }
|
395 | else {
|
396 | resolve();
|
397 | }
|
398 | });
|
399 |
|
400 | promise.then(function() {
|
401 | var entries = conf.entries || config.entries;
|
402 | var stream = gulp.src(entries)
|
403 | .pipe(count({
|
404 |
|
405 | getFileCount: function(entriesCount) {
|
406 | gulpFileCount.filecount = entriesCount;
|
407 | }
|
408 | }))
|
409 | .pipe(gulpif(!conf.inline, findResource(env)))
|
410 |
|
411 | if (conf.custom && conf.custom.html && conf.custom.html.length) {
|
412 | conf.custom.html.forEach(function (task) {
|
413 | stream = stream.pipe(task.func(task.opts));
|
414 | });
|
415 | }
|
416 |
|
417 | stream = stream.pipe(gulpif(conf.inline, addInlineAttr()))
|
418 | .pipe(gulpif(conf.inline, inlinesource()))
|
419 | .pipe(gulpif(conf.minifyHTML, htmlmin()))
|
420 | .on('error', function() {
|
421 | logger.notice('构建失败::>_<::');
|
422 | })
|
423 | .pipe(gulp.dest(htmlTarget))
|
424 | .on('end', function() {
|
425 | if (conf.codeCount) {
|
426 | handleCount();
|
427 | }
|
428 | if (!conf.bundle) {
|
429 | logger.notice('构建完成=^_^=');
|
430 | }
|
431 | })
|
432 | });
|
433 |
|
434 | |
435 |
|
436 |
|
437 | if (config.moveList && config.moveList.length) {
|
438 | config.moveList.forEach(function (moveItem) {
|
439 |
|
440 |
|
441 |
|
442 |
|
443 |
|
444 |
|
445 |
|
446 |
|
447 |
|
448 |
|
449 | gulp.src(moveItem).pipe(gulp.dest(conf.output))
|
450 | gulp.src(path.join(moveItem, '**')).pipe(gulp.dest(conf.output))
|
451 |
|
452 | })
|
453 | }
|
454 |
|
455 |
|
456 |
|
457 | }
|
458 |
|
459 |
|
460 | |
461 |
|
462 |
|
463 | del(conf.output).then(paths => {
|
464 | run();
|
465 | });
|
466 |
|
467 | |
468 |
|
469 |
|
470 | handleWatch(run, conf);
|
471 |
|
472 | |
473 |
|
474 |
|
475 | handleServer(conf.server, config, port);
|
476 | }
|