1 | 'use strict';
|
2 |
|
3 | var fancyLog = require('fancy-log');
|
4 | var PluginError = require('plugin-error');
|
5 | var supportsColor = require('supports-color');
|
6 | var File = require('vinyl');
|
7 | var MemoryFileSystem = require('memory-fs');
|
8 | var nodePath = require('path');
|
9 | var through = require('through');
|
10 | var ProgressPlugin = require('webpack/lib/ProgressPlugin');
|
11 | var clone = require('lodash.clone');
|
12 | var some = require('lodash.some');
|
13 |
|
14 | var defaultStatsOptions = {
|
15 | colors: supportsColor.stdout.hasBasic,
|
16 | hash: false,
|
17 | timings: false,
|
18 | chunks: false,
|
19 | chunkModules: false,
|
20 | modules: false,
|
21 | children: true,
|
22 | version: true,
|
23 | cached: false,
|
24 | cachedAssets: false,
|
25 | reasons: false,
|
26 | source: false,
|
27 | errorDetails: false
|
28 | };
|
29 |
|
30 | module.exports = function (options, wp, done) {
|
31 | options = clone(options) || {};
|
32 | var config = options.config || options;
|
33 | if (typeof done !== 'function') {
|
34 | var callingDone = false;
|
35 | done = function (err, stats) {
|
36 | if (err) {
|
37 |
|
38 | return;
|
39 | }
|
40 | stats = stats || {};
|
41 | if (options.quiet || callingDone) {
|
42 | return;
|
43 | }
|
44 |
|
45 |
|
46 | if (options.watch) {
|
47 | callingDone = true;
|
48 | setTimeout(function () {
|
49 | callingDone = false;
|
50 | }, 500);
|
51 | }
|
52 |
|
53 | if (options.verbose) {
|
54 | fancyLog(stats.toString({
|
55 | colors: supportsColor.stdout.hasBasic
|
56 | }));
|
57 | } else {
|
58 | var statsOptions = (options && options.stats) || {};
|
59 |
|
60 | Object.keys(defaultStatsOptions).forEach(function (key) {
|
61 | if (typeof statsOptions[key] === 'undefined') {
|
62 | statsOptions[key] = defaultStatsOptions[key];
|
63 | }
|
64 | });
|
65 |
|
66 | fancyLog(stats.toString(statsOptions));
|
67 | }
|
68 | };
|
69 | }
|
70 |
|
71 | var webpack = wp || require('webpack');
|
72 | var entry = [];
|
73 | var entries = Object.create(null);
|
74 |
|
75 | var stream = through(function (file) {
|
76 | if (file.isNull()) {
|
77 | return;
|
78 | }
|
79 | if ('named' in file) {
|
80 | if (!Array.isArray(entries[file.named])) {
|
81 | entries[file.named] = [];
|
82 | }
|
83 | entries[file.named].push(file.path);
|
84 | } else {
|
85 | entry = entry || [];
|
86 | entry.push(file.path);
|
87 | }
|
88 | }, function () {
|
89 | var self = this;
|
90 | var handleConfig = function (config) {
|
91 | config.output = config.output || {};
|
92 | config.watch = !!options.watch;
|
93 |
|
94 |
|
95 | if (Object.keys(entries).length > 0) {
|
96 | entry = entries;
|
97 | if (!config.output.filename) {
|
98 |
|
99 | config.output.filename = '[name].js';
|
100 | }
|
101 | } else if (entry.length < 2) {
|
102 | entry = entry[0] || entry;
|
103 | }
|
104 |
|
105 | config.entry = config.entry || entry;
|
106 | config.output.path = config.output.path || process.cwd();
|
107 | config.output.filename = config.output.filename || '[hash].js';
|
108 | config.watch = options.watch;
|
109 | entry = [];
|
110 |
|
111 | if (!config.entry || config.entry.length < 1) {
|
112 | fancyLog('webpack-stream - No files given; aborting compilation');
|
113 | self.emit('end');
|
114 | return false;
|
115 | }
|
116 | return true;
|
117 | };
|
118 |
|
119 | var succeeded;
|
120 | if (Array.isArray(config)) {
|
121 | for (var i = 0; i < config.length; i++) {
|
122 | succeeded = handleConfig(config[i]);
|
123 | if (!succeeded) {
|
124 | return false;
|
125 | }
|
126 | }
|
127 | } else {
|
128 | succeeded = handleConfig(config);
|
129 | if (!succeeded) {
|
130 | return false;
|
131 | }
|
132 | }
|
133 |
|
134 | var compiler = webpack(config, function (err, stats) {
|
135 | if (err) {
|
136 | self.emit('error', new PluginError('webpack-stream', err));
|
137 | return;
|
138 | }
|
139 | var jsonStats = stats ? stats.toJson() || {} : {};
|
140 | var errors = jsonStats.errors || [];
|
141 | if (errors.length) {
|
142 | var errorMessage = errors.join('\n');
|
143 | var compilationError = new PluginError('webpack-stream', errorMessage);
|
144 | if (!options.watch) {
|
145 | self.emit('error', compilationError);
|
146 | }
|
147 | self.emit('compilation-error', compilationError);
|
148 | }
|
149 | if (!options.watch) {
|
150 | self.queue(null);
|
151 | }
|
152 | done(err, stats);
|
153 | if (options.watch && !options.quiet) {
|
154 | fancyLog('webpack is watching for changes');
|
155 | }
|
156 | });
|
157 |
|
158 | var handleCompiler = function (compiler) {
|
159 |
|
160 |
|
161 | if (options.watch && compiler.compiler) {
|
162 | compiler = compiler.compiler;
|
163 | }
|
164 |
|
165 | if (options.progress) {
|
166 | compiler.apply(new ProgressPlugin(function (percentage, msg) {
|
167 | percentage = Math.floor(percentage * 100);
|
168 | msg = percentage + '% ' + msg;
|
169 | if (percentage < 10) msg = ' ' + msg;
|
170 | fancyLog('webpack', msg);
|
171 | }));
|
172 | }
|
173 |
|
174 | var fs = compiler.outputFileSystem = new MemoryFileSystem();
|
175 |
|
176 | var afterEmitPlugin = compiler.hooks
|
177 |
|
178 | ? function (callback) { compiler.hooks.afterEmit.tapAsync('WebpackStream', callback); }
|
179 |
|
180 | : function (callback) { compiler.plugin('after-emit', callback); };
|
181 |
|
182 | afterEmitPlugin(function (compilation, callback) {
|
183 | Object.keys(compilation.assets).forEach(function (outname) {
|
184 | if (compilation.assets[outname].emitted) {
|
185 | var file = prepareFile(fs, compiler, outname);
|
186 | self.queue(file);
|
187 | }
|
188 | });
|
189 | callback();
|
190 | });
|
191 | };
|
192 |
|
193 | if (Array.isArray(options.config) && options.watch) {
|
194 | compiler.watchings.forEach(function (compiler) {
|
195 | handleCompiler(compiler);
|
196 | });
|
197 | } else if (Array.isArray(options.config)) {
|
198 | compiler.compilers.forEach(function (compiler) {
|
199 | handleCompiler(compiler);
|
200 | });
|
201 | } else {
|
202 | handleCompiler(compiler);
|
203 | }
|
204 | });
|
205 |
|
206 |
|
207 | var hasEntry = Array.isArray(config)
|
208 | ? some(config, function (c) { return c.entry; })
|
209 | : config.entry;
|
210 | if (hasEntry) {
|
211 | stream.end();
|
212 | }
|
213 |
|
214 | return stream;
|
215 | };
|
216 |
|
217 | function prepareFile (fs, compiler, outname) {
|
218 | var path = fs.join(compiler.outputPath, outname);
|
219 | if (path.indexOf('?') !== -1) {
|
220 | path = path.split('?')[0];
|
221 | }
|
222 |
|
223 | var contents = fs.readFileSync(path);
|
224 |
|
225 | var file = new File({
|
226 | base: compiler.outputPath,
|
227 | path: nodePath.join(compiler.outputPath, outname),
|
228 | contents: contents
|
229 | });
|
230 | return file;
|
231 | }
|
232 |
|
233 |
|
234 | Object.defineProperty(module.exports, 'webpack', {
|
235 | get: function () {
|
236 | return require('webpack');
|
237 | }
|
238 | });
|