1 | var _ = require('lodash');
|
2 | var async = require('async');
|
3 | var fs = require('graceful-fs');
|
4 | var glob = require('glob');
|
5 | var iconv = require('iconv-lite');
|
6 | var mkdirp = require('mkdirp');
|
7 | var mutil = require('miaow-util');
|
8 | var path = require('path');
|
9 | var Tapable = require('tapable');
|
10 |
|
11 | var TaskContext = require('./TaskContext');
|
12 |
|
13 | function Compilation() {
|
14 | Tapable.call(this);
|
15 | _.bindAll(this);
|
16 |
|
17 | this.modules = {};
|
18 |
|
19 |
|
20 | this.emitModules = {};
|
21 | }
|
22 |
|
23 | Compilation.prototype = Object.create(Tapable.prototype);
|
24 | Compilation.prototype.constructor = Compilation;
|
25 |
|
26 | Compilation.prototype.getFiles = function(callback) {
|
27 | glob('**/*', {
|
28 | cwd: this.context,
|
29 | ignore: this.exclude.concat(['**/miaow.config.js']),
|
30 | nodir: true
|
31 | }, function(err, files) {
|
32 | callback(err, (files || []).map(function(file) {
|
33 | return mutil.relative('', file);
|
34 | }));
|
35 | });
|
36 | };
|
37 |
|
38 |
|
39 | Compilation.prototype.createModules = function(files, callback) {
|
40 | async.map(files, this.createModule, callback);
|
41 | };
|
42 |
|
43 | Compilation.prototype.createModule = function(file, contents, callback) {
|
44 | if (_.isFunction(contents)) {
|
45 | callback = contents;
|
46 | contents = null;
|
47 | }
|
48 |
|
49 | this.factory.create(file, contents, function(err, module) {
|
50 | if (!err) {
|
51 | this.modules[module.src] = module;
|
52 | }
|
53 |
|
54 | callback(err, module);
|
55 | }.bind(this));
|
56 | };
|
57 |
|
58 | Compilation.prototype.buildModules = function(modules, callback) {
|
59 | this.applyPluginsAsyncSeries('build-modules', this.modules, function(err) {
|
60 | if (err) {
|
61 | return callback(err);
|
62 | }
|
63 |
|
64 | async.eachSeries(
|
65 | this.modules,
|
66 | this.buildModule,
|
67 | callback);
|
68 | }.bind(this));
|
69 | };
|
70 |
|
71 | Compilation.prototype.buildModule = function(module, callback) {
|
72 | var taskContext = new TaskContext(this, module);
|
73 |
|
74 | this.applyPluginsAsyncSeries('build-module', module, taskContext, function(err) {
|
75 | if (err) {
|
76 | return callback(err);
|
77 | }
|
78 |
|
79 | module.doBuild(taskContext).then(function() {
|
80 | callback(null, module);
|
81 | }, callback);
|
82 | });
|
83 | };
|
84 |
|
85 | Compilation.prototype.resolveFile = function(context, request, options, callback) {
|
86 | if (_.isFunction(options)) {
|
87 | callback = options;
|
88 | options = {};
|
89 | }
|
90 |
|
91 | this.resolver.resolve(context, request, options, callback);
|
92 | };
|
93 |
|
94 | Compilation.prototype.resolveModule = function(context, request, options, callback) {
|
95 | if (_.isFunction(options)) {
|
96 | callback = options;
|
97 | options = {};
|
98 | }
|
99 |
|
100 |
|
101 | var moduleSchemaRegexp = /^module:\/\//;
|
102 | if (moduleSchemaRegexp.test(request)) {
|
103 | var module = this.modules[request.replace(moduleSchemaRegexp, '')];
|
104 | return callback(module ? null : new Error(request + '未被查找到!'), module);
|
105 | }
|
106 |
|
107 | this.resolver.resolve(context, request, options, function(err, file) {
|
108 | if (err) {
|
109 | return callback(err);
|
110 | }
|
111 |
|
112 | var src = mutil.relative(this.context, file);
|
113 |
|
114 | var module = this.modules[src];
|
115 |
|
116 | if (module) {
|
117 | this.buildModule(module, callback);
|
118 | } else {
|
119 | async.waterfall([
|
120 | this.createModule.bind(this, src),
|
121 | this.buildModule
|
122 | ], callback);
|
123 | }
|
124 | }.bind(this));
|
125 | };
|
126 |
|
127 | Compilation.prototype.emitFile = function(dest, contents, charset, callback) {
|
128 | if (!/utf[\-]?8/i.test(charset)) {
|
129 | contents = iconv.encode(contents.toString(), charset);
|
130 | }
|
131 |
|
132 | var abspath = path.resolve(this.output, dest);
|
133 |
|
134 | async.series([
|
135 | _.partial(mkdirp, path.dirname(abspath)),
|
136 | fs.writeFile.bind(fs, abspath, contents)
|
137 | ], callback);
|
138 | };
|
139 |
|
140 | Compilation.prototype.emitModule = function(src, contents, callback) {
|
141 | src = mutil.relative('', src);
|
142 |
|
143 | var module = this.modules[src];
|
144 |
|
145 | if (module) {
|
146 | this.buildModule(module, callback);
|
147 | } else {
|
148 | async.waterfall([
|
149 | this.createModule.bind(this, src, contents),
|
150 | function(module, callback) {
|
151 | this.emitModules[src] = module;
|
152 | callback(null, module);
|
153 | }.bind(this),
|
154 | this.buildModule
|
155 | ], callback);
|
156 | }
|
157 | };
|
158 |
|
159 |
|
160 | Compilation.prototype.seal = function(callback) {
|
161 | async.waterfall([
|
162 | this.getFiles,
|
163 | this.createModules,
|
164 | this.buildModules
|
165 | ], callback);
|
166 | };
|
167 |
|
168 | module.exports = Compilation;
|