UNPKG

9.26 kBJavaScriptView Raw
1/**
2 * Created by Rodey on 2017/6/29.
3 */
4'use strict';
5
6const extend = require('extend'),
7 plumber = require('gulp-plumber'),
8 util = require('../utils'),
9 publish = require('../plugins/publish'),
10 T = require('../tools');
11
12class TaskNode {
13 /**
14 * 任务
15 * @param config 任务配置
16 * @param gupack Gupack对象
17 */
18 constructor(config, gupack) {
19 this.name = undefined;
20 this.src = '';
21 this.filters = '';
22 this.plugins = [];
23 this.watch = [];
24 this.run = true;
25 this.noWatch = false;
26 this.dest = null;
27 this.rely = undefined;
28 this.loader = {};
29 this.pathPrefix = '';
30 this.base = T.getArg('cwdir') || process.cwd();
31 this.gupack = undefined;
32 this._if = undefined;
33 this.pluginCache = {};
34 this.merge = false;
35 this.stream = null;
36 // 编译前
37 this.before = null;
38 // 编译后
39 this.after = null;
40 // 编译当前任务前清理对应输出目录
41 this.beforeClean = false;
42
43 for (let prop in config) {
44 if (config.hasOwnProperty(prop)) {
45 this[prop] = config[prop];
46 }
47 }
48
49 if (gupack) {
50 this.gupack = gupack;
51 this.gulp = this.gupack.gulp;
52 this.basePath = this.gupack.basePath;
53 this.sourceDir = this.gupack.sourceDir;
54 this.buildDir = this.gupack.buildDir;
55 }
56
57 this.init();
58 }
59
60 init() {
61 //watcher
62 if (!this.noWatch || this.watch) this.watch = this.getTaskWatch();
63
64 //源文件 src
65 this.src = this.getSource();
66
67 //过滤文件 filters
68 this.filters = this.getFilters();
69 this.src = this.src.concat(this.filters);
70
71 //插件样式
72 this.plugins = this.getPlugins();
73 this.src = this.src.concat(this.plugins);
74
75 //合并压缩后的输出
76 this.dest = this.getDist();
77 }
78
79 getTaskWatch() {
80 let source = this.src || [],
81 watcher = this.watch || source || [],
82 pathPrefix = this.pathPrefix || '';
83
84 if (!this.watch && this.pathPrefix.length > 0) {
85 if (util.isString(source)) {
86 watcher = T.Path.join(pathPrefix, source);
87 } else if (util.isArray(source)) {
88 watcher = source.map(s => {
89 return T.Path.join(pathPrefix, s);
90 });
91 } else {
92 throw new ReferenceError('没有可用的源文件,请设置需要监听的文件或目录');
93 }
94 }
95 if (!this.noWatch) {
96 watcher = this.loadWatch(watcher);
97 }
98 return watcher;
99 }
100
101 getSource() {
102 let source = this.src || [],
103 pathPrefix = this.pathPrefix || '';
104 source && source.length !== 0 && (source = this.loadSource(source, pathPrefix));
105 return source;
106 }
107
108 getFilters() {
109 let filters = this.filters || [];
110 if (filters.length > 0) {
111 filters = this.loadSource(filters, this.pathPrefix, '!');
112 }
113 return filters;
114 }
115
116 getPlugins() {
117 let plugins = this.plugins || [];
118 if (plugins.length > 0) {
119 plugins = this.loadSource(plugins, this.pathPrefix);
120 }
121 return plugins;
122 }
123
124 getDist() {
125 return this.dest && T.Path.resolve(this.buildDir, this.dest);
126 }
127
128 getTaskFunction(done) {
129 // 加载的gulp插件,
130 let loaders = this.loader;
131 this.stream = this.gulp.src(this.src);
132
133 // 如果 loader 为Function,则必须返回stream
134 if (util.isFunction(loaders)) {
135 this.stream = loaders.call(this, this.stream, done) || this.stream;
136 // this.stream && this.excuteDest();
137 // return done();
138 return this.stream;
139 }
140
141 this.stream = this.stream.pipe(plumber());
142
143 // 执行编译前 (必须返回stream)
144 if (util.isFunction(this.before)) {
145 this.stream = this.before.call(this, this.stream, done) || this.stream;
146 }
147
148 // 执行加载loader
149 this.excuteLoader(loaders, done);
150
151 // 判断是否存在hostname配置,如果存在则执行替换任务(一般在release)
152 this.excutePublish();
153
154 // 执行编译后
155 if (util.isFunction(this.after)) {
156 this.stream = this.after.call(this, this.stream, done) || this.stream;
157 }
158
159 this.stream = this.stream.pipe(plumber());
160
161 // 输出
162 this.excuteDest();
163
164 return this.stream;
165 }
166
167 loadWatch(source, pathPrefix) {
168 pathPrefix = pathPrefix || '';
169 if (!source) return '';
170 if (util.isString(source)) {
171 source = T.Path.resolve(this.sourceDir, pathPrefix, source);
172 } else {
173 source = source.map(src => {
174 return T.Path.resolve(this.sourceDir, pathPrefix, src);
175 });
176 }
177 return source;
178 }
179
180 loadSource(source, pathPrefix, nos) {
181 nos = nos || '';
182 pathPrefix = pathPrefix || '';
183 if (!source) return '';
184 if (util.isString(source)) {
185 source = [nos + T.Path.resolve(this.sourceDir, pathPrefix, source)];
186 } else {
187 source = source.map(src => {
188 return nos + T.Path.resolve(this.sourceDir, pathPrefix, src);
189 });
190 }
191 return source;
192 }
193
194 excuteLoader(loaders, done) {
195 process.chdir(this.basePath);
196 this.pluginCache = {};
197
198 util.isObject(loaders) &&
199 !util.isEmptyObject(loaders) &&
200 Object.keys(loaders).forEach(loaderName => {
201 let pluginName = loaderName,
202 plugin = this.pluginCache[pluginName],
203 options = loaders[loaderName];
204
205 if (util.isFunction(options)) {
206 this.stream = options.call(this, this.stream, done);
207 return false;
208 }
209
210 if (!plugin) {
211 plugin = (() => {
212 let ptemp = loaders[loaderName],
213 pp,
214 pluginPath;
215 ptemp && util.isObject(ptemp) && ptemp['pluginName'] && (pluginName = ptemp['pluginName']);
216 if (ptemp && util.isObject(ptemp)) {
217 ptemp['pluginName'] && (pluginName = ptemp['pluginName']);
218 ptemp['pluginPath'] && (pluginPath = ptemp['pluginPath']);
219 }
220
221 // 设置插件路径
222 if (pluginPath) {
223 pluginPath = this.getPluginPath(pluginPath, pluginName);
224 pp = require(pluginPath);
225 } else {
226 try {
227 // 从项目src/node_modeuls中找
228 pp = require(T.Path.resolve(this.basePath, `node_modules/${pluginName}/`));
229 } catch (e) {
230 // 从gupack中的node_modules中找
231 pp = require(pluginName);
232 }
233 }
234 if (!pp) {
235 T.log.error(`'${loaderName}' plugin is not loaded, Stream content is not supported`);
236 }
237 pp && (this.pluginCache[pluginName] = pp);
238 return pp;
239 })();
240 }
241
242 // 某些插件需要区分环境,
243 // 可能在开发环境不需要执行,而在生产或测试环境需要执行
244 if (plugin && util.isObject(options) && '_if' in options) {
245 options._if === true && (this.stream = this.stream.pipe(plugin(options)));
246 } else {
247 this.stream = this.stream.pipe(plugin(options));
248 }
249 });
250 }
251
252 excutePublish() {
253 if (!util.isEmptyObject(this.gupack.statics) && this.gupack.statics !== false) {
254 this.stream = this.stream.pipe(publish(this.gupack.statics));
255 }
256 }
257
258 excuteDest() {
259 if (this.dest) {
260 // if (!T.fs.existsSync(this.dest)) {
261 // T.fsa.mkdirsSync(this.dest);
262 // }
263 this.stream = this.stream.pipe(this.gulp.dest(this.dest || this.buildDir));
264 }
265 }
266
267 // 获取自定义插件路径
268 getPluginPath(pluginPath, pluginName) {
269 if (!T.isAbsolutePath(pluginPath)) {
270 pluginPath = T.Path.resolve(this.basePath, pluginPath);
271 }
272 if (!/.js$/i.test(pluginPath)) {
273 pluginPath = T.Path.resolve(pluginPath, pluginName);
274 }
275 return pluginPath;
276 }
277}
278
279module.exports = TaskNode;