1 | const fs = require('fs');
|
2 | const fse = require('fs-extra');
|
3 | const path = require('path');
|
4 | const http = require('http');
|
5 | const net = require('net');
|
6 | const ora = require('ora');
|
7 | const uuid = require('uuid');
|
8 | const chalk = require('chalk');
|
9 | const Gauge = require('gauge');
|
10 | const crypto = require('crypto');
|
11 | const chokidar = require('chokidar');
|
12 | const notifier = require('node-notifier');
|
13 | const ipv4 = require('internal-ip').v4.sync();
|
14 | const child_process = require('child_process');
|
15 | const utils = require('../utils');
|
16 | const logger = require('../utils/logger');
|
17 | const builder = require('./builder');
|
18 | const config = require('../../config');
|
19 | const ansiHtml = require('./ansiHtml');
|
20 | const mine = require('../utils/mine').types;
|
21 |
|
22 | let socketAlready = false;
|
23 | let socketTimeout = null;
|
24 | let socketClients = [];
|
25 | let fileMd5Lists = {};
|
26 |
|
27 | module.exports = {
|
28 | |
29 |
|
30 |
|
31 |
|
32 |
|
33 | portIsOccupied(port, callback) {
|
34 | const server = net.createServer().listen(port);
|
35 | server.on('listening', () => {
|
36 | server.close();
|
37 | callback(null, port);
|
38 | });
|
39 | server.on('error', (err) => {
|
40 | if (err.code === 'EADDRINUSE') {
|
41 | this.portIsOccupied(port + 1, callback);
|
42 | } else {
|
43 | callback(err)
|
44 | }
|
45 | });
|
46 | },
|
47 |
|
48 | |
49 |
|
50 |
|
51 |
|
52 |
|
53 | getHostIndexUrl(dirName) {
|
54 | let indexName = 'index.js';
|
55 | let homePage = utils.getObject(require(path.resolve('eeui.config')), 'homePage').trim();
|
56 | if (utils.count(homePage) > 0) {
|
57 | if (utils.leftExists(homePage, "http://") || utils.leftExists(homePage, "https://") || utils.leftExists(homePage, "ftp://") || utils.leftExists(homePage, "file://")) {
|
58 | return homePage;
|
59 | }
|
60 | let lastUrl = homePage.substring(homePage.lastIndexOf("/"), homePage.length);
|
61 | if (!utils.strExists(lastUrl, ".")) {
|
62 | homePage += ".js";
|
63 | }
|
64 | indexName = homePage;
|
65 | }
|
66 | return dirName + "/" + indexName;
|
67 | },
|
68 |
|
69 | |
70 |
|
71 |
|
72 |
|
73 |
|
74 | urlParamets(url) {
|
75 | let arr;
|
76 | if (utils.strExists(url, "?")) {
|
77 | arr = utils.getMiddle(url, "?", null).split("&");
|
78 | }else{
|
79 | arr = utils.getMiddle(url, "#", null).split("&");
|
80 | }
|
81 | let params = {};
|
82 | for (let i = 0; i < arr.length; i++) {
|
83 | let data = arr[i].split("=");
|
84 | if (data.length === 2) {
|
85 | params[data[0]] = data[1];
|
86 | }
|
87 | }
|
88 | return params;
|
89 | },
|
90 |
|
91 | |
92 |
|
93 |
|
94 |
|
95 |
|
96 | createServer(contentBase, port) {
|
97 | http.createServer((req, res) => {
|
98 | let url = req.url;
|
99 | let file = contentBase + url.split('?').shift();
|
100 | let params = this.urlParamets(url);
|
101 | let suffixName = file.split('.').pop();
|
102 | let stats = utils.pathType(file);
|
103 | switch (stats) {
|
104 | case 1:
|
105 | res.writeHead(200, {'content-type': (mine[suffixName] || "text/plain; charset=utf-8")});
|
106 | if (params.preload === 'preload') {
|
107 | res.write(JSON.stringify({
|
108 | appboards: utils.getAllAppboards(config.sourceDir),
|
109 | body: fs.readFileSync(file, 'utf8'),
|
110 | }));
|
111 | res.end();
|
112 | } else {
|
113 | fs.createReadStream(file).pipe(res);
|
114 | }
|
115 | break;
|
116 |
|
117 | case 2:
|
118 | this.errorServer(res, 405);
|
119 | break;
|
120 |
|
121 | default:
|
122 | this.errorServer(res, 404);
|
123 | break;
|
124 | }
|
125 | }).listen(port);
|
126 | },
|
127 |
|
128 | |
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 | errorServer(res, errorCode, errorMsg) {
|
136 | if (res === true) {
|
137 | let data = fs.readFileSync(path.resolve(__dirname, 'error.js'), 'utf8');
|
138 | data += "";
|
139 | if (errorCode) {
|
140 | data = data.replace('你访问的页面出错了!', '你访问的页面出错了! (' + errorCode + ')')
|
141 | }
|
142 | if (errorMsg) {
|
143 | data = data.replace('var errorMsg=decodeURIComponent("");', 'var errorMsg=decodeURIComponent("' + encodeURIComponent(errorMsg.replace(new RegExp(path.resolve(__dirname, '../../'), 'g'), '')) + '");')
|
144 | }
|
145 | return data;
|
146 | }
|
147 | fs.readFile(path.resolve(__dirname, 'error.js'), (err, data) => {
|
148 | if (err) {
|
149 | res.writeHead(404, { 'content-type': 'text/html' });
|
150 | res.write('<h1>404错误</h1><p>你要找的页面不存在</p>');
|
151 | res.end();
|
152 | } else {
|
153 | data += "";
|
154 | if (errorCode) {
|
155 | data = data.replace('你访问的页面出错了!', '你访问的页面出错了! (' + errorCode + ')')
|
156 | }
|
157 | if (errorMsg) {
|
158 | data = data.replace('var errorMsg=decodeURIComponent("");', 'var errorMsg=decodeURIComponent("' + encodeURIComponent(errorMsg.replace(new RegExp(path.resolve(__dirname, '../../'), 'g'), '')) + '");')
|
159 | }
|
160 | res.writeHead(200, { 'content-type': 'text/javascript; charset=utf-8' });
|
161 | res.write(data);
|
162 | res.end();
|
163 | }
|
164 | });
|
165 | },
|
166 |
|
167 | |
168 |
|
169 |
|
170 |
|
171 | completeCode(assetsByChunkName) {
|
172 | utils.each(assetsByChunkName, (key, value) => {
|
173 | let assetPath = path.resolve(config.distDir, config.sourcePagesDir, value);
|
174 | let assetContent = fs.readFileSync(assetPath, 'utf8');
|
175 | let isEdit = false;
|
176 | if (!/^\/\/\s*{\s*"framework"\s*:\s*"Vue"\s*}/.exec(assetContent)) {
|
177 | assetContent = `// { "framework": "Vue"} \n` + assetContent;
|
178 | isEdit = true;
|
179 | }
|
180 | if (/((\s|{|\[|\(|,|;)console)\.(debug|log|info|warn|error)\((.*?)\)/.exec(assetContent)) {
|
181 | assetContent = utils.replaceEeuiLog(assetContent);
|
182 | isEdit = true;
|
183 | }
|
184 | if (/\.(requireModule|isRegisteredModule)\((['"])(eeui\/.*)\2\)/.exec(assetContent)) {
|
185 | assetContent = utils.replaceModule(assetContent);
|
186 | isEdit = true;
|
187 | }
|
188 | if (isEdit) {
|
189 | fs.writeFileSync(assetPath, assetContent);
|
190 | }
|
191 | });
|
192 | },
|
193 |
|
194 | |
195 |
|
196 |
|
197 |
|
198 |
|
199 |
|
200 | copyOtherFile(originDir, newDir, containAppboardDir) {
|
201 | let lists = fs.readdirSync(originDir);
|
202 | let appboardDir = path.resolve(config.sourceDir, 'appboard');
|
203 | lists.some((item) => {
|
204 | if (!utils.execPath(item)) {
|
205 | return false;
|
206 | }
|
207 | let originPath = path.resolve(originDir, item);
|
208 | let newPath = path.resolve(newDir, item);
|
209 | let stats = utils.pathType(originPath);
|
210 | if (stats === 1) {
|
211 | if (utils.leftExists(originPath, appboardDir)) {
|
212 | if (containAppboardDir === true) {
|
213 | let originContent = fs.readFileSync(originPath, 'utf8');
|
214 | fse.outputFileSync(newPath, utils.replaceModule(utils.replaceEeuiLog(originContent)));
|
215 | }
|
216 | } else {
|
217 | fse.copySync(originPath, newPath);
|
218 | }
|
219 | } else if (stats === 2) {
|
220 | this.copyOtherFile(originPath, newPath, containAppboardDir)
|
221 | }
|
222 | });
|
223 | },
|
224 |
|
225 | |
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 | copyFileMd5(originPath, newPath, callback) {
|
232 | let stream = fs.createReadStream(originPath);
|
233 | let md5sum = crypto.createHash('md5');
|
234 | stream.on('data', (chunk) => {
|
235 | md5sum.update(chunk);
|
236 | });
|
237 | stream.on('end', () => {
|
238 | let str = md5sum.digest("hex").toUpperCase();
|
239 | if (fileMd5Lists[newPath] !== str) {
|
240 | fileMd5Lists[newPath] = str;
|
241 | fse.copy(originPath, newPath, callback);
|
242 | }
|
243 | });
|
244 | },
|
245 |
|
246 | |
247 |
|
248 |
|
249 |
|
250 | appboardGulpBabel(task) {
|
251 | let gulpBin = path.resolve('node_modules/gulp/bin/gulp.js');
|
252 | let gulpFile = path.resolve('gulpfile.js');
|
253 | if (!fs.existsSync(gulpBin) || !fs.existsSync(gulpFile)) {
|
254 | return false;
|
255 | }
|
256 |
|
257 | let spinFetch = ora('babel appboard...');
|
258 | spinFetch.start();
|
259 | try {
|
260 | child_process.execSync("node " + gulpBin + " --gulpfile " + gulpFile + " " + (task || "default"), {encoding: 'utf8'});
|
261 | spinFetch.stop();
|
262 | return true;
|
263 | } catch (e) {
|
264 | spinFetch.stop();
|
265 | return false;
|
266 | }
|
267 | },
|
268 |
|
269 | |
270 |
|
271 |
|
272 |
|
273 |
|
274 |
|
275 |
|
276 | syncFolderAndWebSocket(host, port, socketPort, removeBundlejs) {
|
277 | let isSocket = !!(host && socketPort);
|
278 | let hostUrl = 'http://' + host + ':' + port + "/";
|
279 |
|
280 | let jsonData = require(path.resolve('eeui.config'));
|
281 | jsonData.socketHost = host ? host : '';
|
282 | jsonData.socketPort = socketPort ? socketPort : '';
|
283 | jsonData.socketHome = isSocket ? this.getHostIndexUrl(hostUrl + config.sourcePagesDir) : '';
|
284 |
|
285 | let random = Math.random();
|
286 | let deviceIds = {};
|
287 |
|
288 | let copyJsEvent = (originDir, newDir, rootDir) => {
|
289 | let lists = fs.readdirSync(originDir);
|
290 | lists.some((item) => {
|
291 | if (!utils.execPath(item)) {
|
292 | return false;
|
293 | }
|
294 | let originPath = path.resolve(originDir, item);
|
295 | let newPath = path.resolve(newDir, item);
|
296 | let stats = utils.pathType(originPath);
|
297 | if (stats === 1) {
|
298 | this.copyFileMd5(originPath, newPath, (err) => {
|
299 | if (err || !socketAlready) {
|
300 | return;
|
301 | }
|
302 | socketClients.some((client) => {
|
303 | let deviceKey = client.deviceId + hostUrl + rootDir + item;
|
304 | if (client.ws.readyState !== 2 && deviceIds[deviceKey] !== random) {
|
305 | deviceIds[deviceKey] = random;
|
306 | setTimeout(() => {
|
307 | utils.sendWebSocket(client.ws, client.version, {
|
308 | type: "RELOADPAGE",
|
309 | value: hostUrl + rootDir + item,
|
310 | });
|
311 | }, 300);
|
312 | }
|
313 | });
|
314 | });
|
315 | } else if (stats === 2) {
|
316 | copyJsEvent(originPath, newPath, (rootDir || "") + item + "/")
|
317 | }
|
318 | });
|
319 | };
|
320 |
|
321 | let mainPath = path.resolve('platforms/android/eeuiApp/app/src/main/assets/eeui');
|
322 | let bundlejsPath = path.resolve('platforms/ios/eeuiApp/bundlejs/eeui');
|
323 | if (removeBundlejs) {
|
324 | fse.removeSync(mainPath);
|
325 | fse.removeSync(bundlejsPath);
|
326 | fse.outputFile(path.resolve(mainPath, 'config.json'), JSON.stringify(jsonData, null, "\t"));
|
327 | fse.outputFile(path.resolve(bundlejsPath, 'config.json'), JSON.stringify(jsonData, null, "\t"));
|
328 | }
|
329 | copyJsEvent(path.resolve(config.distDir), mainPath);
|
330 | copyJsEvent(path.resolve(config.distDir), bundlejsPath);
|
331 |
|
332 | if (isSocket) {
|
333 | if (socketAlready === false) {
|
334 | socketAlready = true;
|
335 | let WebSocketServer = require('ws').Server,
|
336 | wss = new WebSocketServer({port: socketPort});
|
337 | wss.on('connection', (ws, info) => {
|
338 | let deviceId = uuid.v4();
|
339 | let mode = utils.getQueryString(info.url, "mode");
|
340 | let version = utils.runNum(utils.getQueryString(info.url, "version"));
|
341 | socketClients.push({deviceId, ws, version});
|
342 | ws.on('close', () => {
|
343 | socketClients.some((socketItem, i) => {
|
344 | if (socketItem.deviceId === deviceId) {
|
345 | socketClients.splice(i, 1);
|
346 | return true;
|
347 | }
|
348 | });
|
349 | });
|
350 |
|
351 | switch (mode) {
|
352 | case "initialize":
|
353 | utils.sendWebSocket(ws, version, {
|
354 | type: "HOMEPAGE",
|
355 | value: this.getHostIndexUrl(hostUrl + config.sourcePagesDir),
|
356 | appboards: utils.getAllAppboards(config.sourceDir)
|
357 | });
|
358 | break;
|
359 |
|
360 | case "back":
|
361 | utils.sendWebSocket(ws, version, {
|
362 | type: "HOMEPAGEBACK",
|
363 | value: this.getHostIndexUrl(hostUrl + config.sourcePagesDir),
|
364 | appboards: utils.getAllAppboards(config.sourceDir)
|
365 | });
|
366 | break;
|
367 |
|
368 | case "reconnect":
|
369 | utils.sendWebSocket(ws, version, {
|
370 | type: "RECONNECT",
|
371 | value: this.getHostIndexUrl(hostUrl + config.sourcePagesDir),
|
372 | appboards: utils.getAllAppboards(config.sourceDir)
|
373 | });
|
374 | break;
|
375 | }
|
376 | });
|
377 | }
|
378 | notifier.notify({
|
379 | title: 'WiFi真机同步',
|
380 | message: jsonData.socketHost + ':' + jsonData.socketPort,
|
381 | contentImage: path.join(__dirname, 'logo.png')
|
382 | });
|
383 | socketTimeout && clearInterval(socketTimeout);
|
384 | socketTimeout = setTimeout(() => {
|
385 | let msg = '';
|
386 | msg+= chalk.bgGreen.bold.black(`【WiFI真机同步】`);
|
387 | msg+= chalk.bgGreen.black(`IP地址: `);
|
388 | msg+= chalk.bgGreen.bold.black.underline(`${jsonData.socketHost}`);
|
389 | msg+= chalk.bgGreen.black(`、端口号: `);
|
390 | msg+= chalk.bgGreen.bold.black.underline(`${jsonData.socketPort}`);
|
391 | console.log(); console.log(msg); console.log();
|
392 | }, 200);
|
393 | } else {
|
394 | child_process.fork(path.join(__dirname, 'buildNotify.js'));
|
395 | }
|
396 | },
|
397 |
|
398 | |
399 |
|
400 |
|
401 | compressBuildDir() {
|
402 | let zipName = "build-" + utils.formatDate("YmdHis");
|
403 | let expand = require("../utils/expand");
|
404 | if (expand.androidGradle("versionName")) {
|
405 | zipName += "-";
|
406 | zipName += expand.androidGradle("versionName");
|
407 | if (expand.androidGradle("versionCode")) {
|
408 | zipName += "-";
|
409 | zipName += expand.androidGradle("versionCode");
|
410 | }
|
411 | }
|
412 | let zipPackPath = path.resolve(config.zipPackDir);
|
413 | utils.mkdirsSync(zipPackPath);
|
414 | utils.zipCompress({
|
415 | output: zipPackPath + "/" + zipName + ".zip",
|
416 | entry: [{
|
417 | type: 'dir',
|
418 | path: path.resolve(config.distDir)
|
419 | }]
|
420 | });
|
421 | },
|
422 |
|
423 | |
424 |
|
425 |
|
426 |
|
427 |
|
428 | dev(isOnce) {
|
429 | let gauge = new Gauge();
|
430 | let progress = 0;
|
431 | let options = {
|
432 | ext: 'vue',
|
433 | watch: !isOnce,
|
434 | minimize: false,
|
435 | devtool: false,
|
436 | mode: 'development',
|
437 | onProgress: (complete, action) => {
|
438 | if (complete > progress) {
|
439 | progress = complete;
|
440 | } else {
|
441 | complete = progress;
|
442 | }
|
443 | gauge.show(action, complete);
|
444 | }
|
445 | };
|
446 | if (fs.existsSync(path.resolve('babel.config.js'))) {
|
447 | options.babelOptions = require(path.resolve('babel.config.js'));
|
448 | } else if (fs.existsSync(path.resolve('.babelrc'))) {
|
449 | options.babelOptions = utils.jsonParse(fs.readFileSync(path.resolve('.babelrc'), 'utf8'));
|
450 | }
|
451 |
|
452 | let serverStatus = 0;
|
453 | let socketPort = config.port;
|
454 | let serverPort = config.port_socket;
|
455 | let buildSuccess = [];
|
456 | let buildCallback = (error, output, info) => {
|
457 | gauge.hide();
|
458 | if (error) {
|
459 | console.log(chalk.red('Build Failed!'));
|
460 | utils.each(typeof error == 'object' ? error : [error], (index, item) => {
|
461 | console.error(item);
|
462 | });
|
463 | utils.each(info.assetsByChunkName, (key, value) => {
|
464 | fs.writeFileSync(path.resolve(config.distDir, config.sourcePagesDir, value), this.errorServer(true, 500, ansiHtml.toHtml(error)));
|
465 | });
|
466 | } else {
|
467 | console.log('Build completed!');
|
468 | console.log(output.toString());
|
469 |
|
470 | this.completeCode(info.assetsByChunkName);
|
471 | if (options.watch) {
|
472 | if (serverStatus === 0) {
|
473 | serverStatus = 1;
|
474 | this.portIsOccupied(serverPort, (err, port) => {
|
475 | if (err) throw err;
|
476 | this.portIsOccupied(socketPort, (err, sPort) => {
|
477 | if (err) throw err;
|
478 | serverPort = port;
|
479 | socketPort = sPort;
|
480 | this.createServer(path.resolve(config.distDir), serverPort);
|
481 | this.copyOtherFile(path.resolve(config.sourceDir), path.resolve(config.distDir), true);
|
482 | this.appboardGulpBabel('appboard-dev');
|
483 | this.syncFolderAndWebSocket(ipv4, serverPort, socketPort, true);
|
484 | serverStatus = 200;
|
485 | });
|
486 | });
|
487 | }
|
488 | } else {
|
489 | this.copyOtherFile(path.resolve(config.sourceDir), path.resolve(config.distDir), true);
|
490 | this.appboardGulpBabel('appboard-dev');
|
491 | this.syncFolderAndWebSocket(null, null, null, true);
|
492 | }
|
493 |
|
494 | buildSuccess.forEach((tmpCallback) => { typeof tmpCallback === "function" && tmpCallback(); });
|
495 | buildSuccess = [];
|
496 | }
|
497 | if (serverStatus === 200) {
|
498 | this.copyOtherFile(path.resolve(config.sourceDir), path.resolve(config.distDir), false);
|
499 | this.syncFolderAndWebSocket(ipv4, serverPort, socketPort, false);
|
500 | }
|
501 | };
|
502 |
|
503 | fse.removeSync(path.resolve(config.distDir));
|
504 | let mBuilder = new builder(`${config.sourceDir}/${config.sourcePagesDir}`, `${config.distDir}/${config.sourcePagesDir}`, options).build(buildCallback);
|
505 |
|
506 | if (options.watch) {
|
507 |
|
508 | let watchListener = (filePath, content) => {
|
509 | if (utils.leftExists(filePath, "appboard/") && utils.rightExists(filePath, ".js") && socketAlready) {
|
510 | content = utils.replaceModule(utils.replaceEeuiLog(content));
|
511 | socketClients.some((client) => {
|
512 | if (client.ws.readyState !== 2) {
|
513 | utils.sendWebSocket(client.ws, client.version, {
|
514 | type: "REFRESH",
|
515 | appboards: [{
|
516 | path: filePath,
|
517 | content: content,
|
518 | }],
|
519 | });
|
520 | }
|
521 | });
|
522 | }
|
523 | };
|
524 |
|
525 | (() => {
|
526 | let appboardDir = path.resolve(config.sourceDir, 'appboard'),
|
527 | sourceDir = config.sourceDir,
|
528 | distDir = config.distDir,
|
529 | sourcePath,
|
530 | sourceName;
|
531 | chokidar.watch(config.sourceDir, {
|
532 | ignored: /[\/\\]\./,
|
533 | persistent: true
|
534 | }).on('all', (event, filePath) => {
|
535 | if (serverStatus !== 200) {
|
536 | return;
|
537 | }
|
538 | sourcePath = path.resolve(filePath);
|
539 | sourceName = path.relative(path.resolve(sourceDir), filePath);
|
540 | if (/^win/.test(process.platform)) {
|
541 | filePath = filePath.replace(/\\/g, "/");
|
542 | sourceName = sourceName.replace(/\\/g, "/");
|
543 | }
|
544 |
|
545 | if (utils.rightExists(filePath, ".vue")) {
|
546 | if (utils.leftExists(filePath, "src/pages/")) {
|
547 | let fileName = path.relative(path.resolve("src/pages/"), filePath).replace(/\.\w+$/, '');
|
548 | if (event === "add") {
|
549 | mBuilder.insertEntry({
|
550 | fileName: fileName,
|
551 | sourcePath: sourcePath + "?entry=true"
|
552 | });
|
553 | } else if (event === "unlink") {
|
554 | mBuilder.removeEntry({
|
555 | fileName: fileName
|
556 | });
|
557 | }
|
558 | }
|
559 | } else if (utils.execPath(sourcePath)) {
|
560 | let distPath = path.resolve(distDir, sourceName);
|
561 | if (sourceName == "entry.js") {
|
562 | notifier.notify({
|
563 | title: 'entry.js',
|
564 | message: "修改的内容需要重编译才生效。",
|
565 | contentImage: path.join(__dirname, 'logo.png')
|
566 | });
|
567 | logger.warn("检测到入口文件[entry.js]已变化,修改的内容需要重新编译才生效。");
|
568 | return;
|
569 | }
|
570 | if (["add", "change"].indexOf(event) !== -1) {
|
571 | let sourceContent = fs.readFileSync(sourcePath, 'utf8');
|
572 | if (utils.leftExists(sourcePath, appboardDir)) {
|
573 | fse.outputFileSync(distPath, utils.replaceModule(utils.replaceEeuiLog(sourceContent)));
|
574 | this.appboardGulpBabel('appboard-dev --filePath ' + distPath);
|
575 | if (fs.existsSync(distPath)) {
|
576 | sourceContent = fs.readFileSync(distPath, 'utf8');
|
577 | }
|
578 | } else {
|
579 | fse.copySync(sourcePath, distPath);
|
580 | }
|
581 | buildSuccess.push(() => { watchListener(sourceName, sourceContent); });
|
582 | mBuilder.webpackInvalidate();
|
583 | } else if (["unlink"].indexOf(event) !== -1) {
|
584 | fse.removeSync(path.resolve(sourceDir, '../platforms/android/eeuiApp/app/src/main/assets/eeui', sourceName));
|
585 | fse.removeSync(path.resolve(sourceDir, '../platforms/ios/eeuiApp/bundlejs/eeui', sourceName));
|
586 | fse.removeSync(distPath);
|
587 | buildSuccess.push(() => { watchListener(sourceName, ""); });
|
588 | mBuilder.webpackInvalidate();
|
589 | }
|
590 | }
|
591 | });
|
592 |
|
593 | chokidar.watch(path.resolve(sourceDir, '../eeui.config.js'), {
|
594 | ignored: /[\/\\]\./,
|
595 | persistent: true
|
596 | }).on('change', (s) => {
|
597 | if (serverStatus !== 200) {
|
598 | return;
|
599 | }
|
600 | notifier.notify({
|
601 | title: 'eeui.config.js',
|
602 | message: "修改的内容需要重编译运行App才生效。",
|
603 | contentImage: path.join(__dirname, 'logo.png')
|
604 | });
|
605 | logger.warn("检测到配置文件[eeui.config.js]已变化,修改的内容可能需要重新编译运行App才起效。");
|
606 | logger.sep();
|
607 | utils.syncConfigToPlatforms();
|
608 | });
|
609 | })();
|
610 | }
|
611 |
|
612 | return mBuilder;
|
613 | },
|
614 |
|
615 | |
616 |
|
617 |
|
618 |
|
619 | build(noZip) {
|
620 | let gauge = new Gauge();
|
621 | let progress = 0;
|
622 | let options = {
|
623 | ext: 'vue',
|
624 | watch: false,
|
625 | minimize: true,
|
626 | devtool: false,
|
627 | mode: 'production',
|
628 | onProgress: (complete, action) => {
|
629 | if (complete > progress) {
|
630 | progress = complete;
|
631 | } else {
|
632 | complete = progress;
|
633 | }
|
634 | gauge.show(action, complete);
|
635 | }
|
636 | };
|
637 | if (fs.existsSync(path.resolve('babel.config.js'))) {
|
638 | options.babelOptions = require(path.resolve('babel.config.js'));
|
639 | } else if (fs.existsSync(path.resolve('.babelrc'))) {
|
640 | options.babelOptions = utils.jsonParse(fs.readFileSync(path.resolve('.babelrc'), 'utf8'));
|
641 | }
|
642 |
|
643 | let buildCallback = (error, output, info) => {
|
644 | gauge.hide();
|
645 | if (error) {
|
646 | console.log(chalk.red('Build Failed!'));
|
647 | utils.each(typeof error == 'object' ? error : [error], (index, item) => {
|
648 | console.error(item);
|
649 | });
|
650 | } else {
|
651 | console.log('Build completed!');
|
652 | console.log(output.toString());
|
653 |
|
654 | this.completeCode(info.assetsByChunkName);
|
655 | this.copyOtherFile(path.resolve(config.sourceDir), path.resolve(config.distDir), true);
|
656 | this.appboardGulpBabel('appboard-build');
|
657 | this.syncFolderAndWebSocket(null, null, null, true);
|
658 | if (noZip !== true) {
|
659 | this.compressBuildDir();
|
660 | }
|
661 | }
|
662 | };
|
663 | fse.removeSync(path.resolve(config.distDir));
|
664 | return new builder(`${config.sourceDir}/${config.sourcePagesDir}`, `${config.distDir}/${config.sourcePagesDir}`, options).build(buildCallback);
|
665 | }
|
666 | }; |
\ | No newline at end of file |