1 | var _ = require('lodash');
|
2 | var async = require('async');
|
3 | var chalk = require('chalk');
|
4 | var chokidar = require('chokidar');
|
5 | var freeport = require('freeport');
|
6 | var fs = require('fs-extra');
|
7 | var mutil = require('miaow-util');
|
8 | var path = require('path');
|
9 |
|
10 | var LiveReload = require('./livereload');
|
11 | var compile = require('./compile');
|
12 | var config = require('./config');
|
13 |
|
14 | function watch(options) {
|
15 | options = config(options);
|
16 |
|
17 | compile(options, function (err, cache) {
|
18 | if (err) {
|
19 | mutil.log(chalk.red.bold('编译失败, 不能启动文件监听模式'));
|
20 |
|
21 | err.showStack = false;
|
22 | console.error(err.toString());
|
23 |
|
24 | process.exit(1);
|
25 | return;
|
26 | }
|
27 |
|
28 |
|
29 | var liveload = new LiveReload(options.liveReloadPort);
|
30 |
|
31 |
|
32 | var compileQueue = async.queue(function (srcPath, cb) {
|
33 | var modifyTime = new Date().getTime();
|
34 | mutil.log('开始编译 ' + chalk.green.underline.bold(srcPath));
|
35 | cache.get(srcPath, function (err) {
|
36 | if (err) {
|
37 | err.showStack = false;
|
38 | console.error(err.toString());
|
39 | return cb();
|
40 | }
|
41 |
|
42 | liveload.change(srcPath, modifyTime);
|
43 | mutil.log('成功编译 ' + chalk.green.underline.bold(srcPath));
|
44 | cb();
|
45 | });
|
46 | }, 1);
|
47 |
|
48 |
|
49 | function getDependedList(srcPath) {
|
50 | var modules = cache.modules;
|
51 | var dependedList = [];
|
52 | var searchList = [srcPath];
|
53 |
|
54 | function isDepend(module, item) {
|
55 | return _.includes(module.dependencies, item);
|
56 | }
|
57 |
|
58 | while (searchList.length) {
|
59 | var _searchList = searchList;
|
60 | searchList = [];
|
61 |
|
62 | _.each(modules, function (module, srcPath) {
|
63 | if (_.any(_searchList, isDepend.bind(this, module))) {
|
64 | dependedList.push(srcPath);
|
65 | searchList.push(srcPath);
|
66 | }
|
67 | });
|
68 | }
|
69 |
|
70 | dependedList.push(srcPath);
|
71 |
|
72 | return dependedList;
|
73 | }
|
74 |
|
75 |
|
76 | function compileChangedFile(filePath) {
|
77 | var srcPath = path.relative(options.cwd, filePath);
|
78 | var fileList = getDependedList(srcPath);
|
79 | var modules = cache.modules;
|
80 |
|
81 | _.each(fileList, function (srcPath) {
|
82 | var module = modules[srcPath];
|
83 |
|
84 | if (module) {
|
85 | try {
|
86 | fs.removeSync(module.destAbsPath);
|
87 | fs.removeSync(module.destAbsPathWithHash);
|
88 | } catch (e) {
|
89 | }
|
90 |
|
91 | delete modules[srcPath];
|
92 | }
|
93 | });
|
94 |
|
95 | mutil.log('修改文件 ' + chalk.underline.bold(srcPath));
|
96 | compileQueue.push(fileList);
|
97 | }
|
98 |
|
99 | function compileAddedFile(filePath) {
|
100 | var srcPath = path.relative(options.cwd, filePath);
|
101 |
|
102 | mutil.log('新增文件 ' + chalk.underline.bold(srcPath));
|
103 | compileQueue.push(srcPath);
|
104 | }
|
105 |
|
106 | function compileDeletedFile(filePath) {
|
107 | var srcPath = path.relative(options.cwd, filePath);
|
108 | var modules = cache.modules;
|
109 |
|
110 | var module = modules[srcPath];
|
111 |
|
112 | if (module) {
|
113 | try {
|
114 | fs.removeSync(module.destAbsPath);
|
115 | fs.removeSync(module.destAbsPathWithHash);
|
116 | } catch (e) {
|
117 | }
|
118 |
|
119 | delete modules[srcPath];
|
120 | }
|
121 |
|
122 | mutil.log('删除文件 ' + chalk.red.underline.bold(srcPath));
|
123 | }
|
124 |
|
125 | var watcher = chokidar.watch('**/*', {cwd: options.cwd, ignored: options.exclude || []})
|
126 | .on('ready', function () {
|
127 | mutil.log('开始监听');
|
128 |
|
129 | watcher.on('add', compileAddedFile);
|
130 | watcher.on('change', compileChangedFile);
|
131 | watcher.on('unlink', compileDeletedFile);
|
132 | });
|
133 | });
|
134 | }
|
135 |
|
136 | module.exports = function (options) {
|
137 | freeport(function (err, port) {
|
138 | if (err) {
|
139 | mutil.log(chalk.red.bold('获取端口失败, 不能启动自动刷新功能'));
|
140 | } else {
|
141 | options.liveReloadPort = port;
|
142 | }
|
143 |
|
144 | watch(options);
|
145 | });
|
146 | };
|