Skip to content

Commit 6b49341

Browse files
grawkSpaceK33z
authored andcommitted
pull up shareable code to lib/util (#140)
1 parent 47fd5bf commit 6b49341

File tree

2 files changed

+246
-230
lines changed

2 files changed

+246
-230
lines changed

lib/Shared.js

+214
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
var parseRange = require("range-parser");
2+
var pathIsAbsolute = require("path-is-absolute");
3+
var MemoryFileSystem = require("memory-fs");
4+
var HASH_REGEXP = /[0-9a-f]{10,}/;
5+
6+
module.exports = function Shared(context) {
7+
var share = {
8+
setOptions: function(options) {
9+
if(!options) options = {};
10+
if(typeof options.watchOptions === "undefined") options.watchOptions = {};
11+
if(typeof options.reporter !== "function") options.reporter = share.defaultReporter;
12+
if(typeof options.log !== "function") options.log = console.log.bind(console);
13+
if(typeof options.warn !== "function") options.warn = console.warn.bind(console);
14+
if(typeof options.watchDelay !== "undefined") {
15+
// TODO remove this in next major version
16+
options.warn("options.watchDelay is deprecated: Use 'options.watchOptions.aggregateTimeout' instead");
17+
options.watchOptions.aggregateTimeout = options.watchDelay;
18+
}
19+
if(typeof options.watchOptions.aggregateTimeout === "undefined") options.watchOptions.aggregateTimeout = 200;
20+
if(typeof options.stats === "undefined") options.stats = {};
21+
if(!options.stats.context) options.stats.context = process.cwd();
22+
if(options.lazy) {
23+
if(typeof options.filename === "string") {
24+
var str = options.filename
25+
.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&")
26+
.replace(/\\\[[a-z]+\\\]/ig, ".+");
27+
options.filename = new RegExp("^[\/]{0,1}" + str + "$");
28+
}
29+
}
30+
context.options = options;
31+
},
32+
defaultReporter: function(reporterOptions) {
33+
var state = reporterOptions.state;
34+
var stats = reporterOptions.stats;
35+
var options = reporterOptions.options;
36+
37+
if(state) {
38+
var displayStats = (!options.quiet && options.stats !== false);
39+
if(displayStats && !(stats.hasErrors() || stats.hasWarnings()) &&
40+
options.noInfo)
41+
displayStats = false;
42+
if(displayStats) {
43+
options.log(stats.toString(options.stats));
44+
}
45+
if(!options.noInfo && !options.quiet) {
46+
options.log("webpack: bundle is now VALID.");
47+
}
48+
} else {
49+
options.log("webpack: bundle is now INVALID.");
50+
}
51+
},
52+
handleRangeHeaders: function handleRangeHeaders(content, req, res) {
53+
//assumes express API. For other servers, need to add logic to access alternative header APIs
54+
res.setHeader("Accept-Ranges", "bytes");
55+
if(req.headers.range) {
56+
var ranges = parseRange(content.length, req.headers.range);
57+
58+
// unsatisfiable
59+
if(-1 == ranges) {
60+
res.setHeader("Content-Range", "bytes */" + content.length);
61+
res.statusCode = 416;
62+
}
63+
64+
// valid (syntactically invalid/multiple ranges are treated as a regular response)
65+
if(-2 != ranges && ranges.length === 1) {
66+
// Content-Range
67+
res.statusCode = 206;
68+
var length = content.length;
69+
res.setHeader(
70+
"Content-Range",
71+
"bytes " + ranges[0].start + "-" + ranges[0].end + "/" + length
72+
);
73+
74+
content = content.slice(ranges[0].start, ranges[0].end + 1);
75+
}
76+
}
77+
return content;
78+
},
79+
setFs: function(compiler) {
80+
if(typeof compiler.outputPath === "string" && !pathIsAbsolute.posix(compiler.outputPath) && !pathIsAbsolute.win32(compiler.outputPath)) {
81+
throw new Error("`output.path` needs to be an absolute path or `/`.");
82+
}
83+
84+
// store our files in memory
85+
var fs;
86+
var isMemoryFs = !compiler.compilers && compiler.outputFileSystem instanceof MemoryFileSystem;
87+
if(isMemoryFs) {
88+
fs = compiler.outputFileSystem;
89+
} else {
90+
fs = compiler.outputFileSystem = new MemoryFileSystem();
91+
}
92+
context.fs = fs;
93+
},
94+
compilerDone: function(stats) {
95+
// We are now on valid state
96+
context.state = true;
97+
context.webpackStats = stats;
98+
99+
// Do the stuff in nextTick, because bundle may be invalidated
100+
// if a change happened while compiling
101+
process.nextTick(function() {
102+
// check if still in valid state
103+
if(!context.state) return;
104+
// print webpack output
105+
context.options.reporter({
106+
state: true,
107+
stats: stats,
108+
options: context.options
109+
});
110+
111+
// execute callback that are delayed
112+
var cbs = context.callbacks;
113+
context.callbacks = [];
114+
cbs.forEach(function continueBecauseBundleAvailable(cb) {
115+
cb(stats);
116+
});
117+
});
118+
119+
// In lazy mode, we may issue another rebuild
120+
if(context.forceRebuild) {
121+
context.forceRebuild = false;
122+
share.rebuild();
123+
}
124+
},
125+
compilerInvalid: function() {
126+
if(context.state && (!context.options.noInfo && !context.options.quiet))
127+
context.options.reporter({
128+
state: false,
129+
options: context.options
130+
});
131+
132+
// We are now in invalid state
133+
context.state = false;
134+
//resolve async
135+
if(arguments.length === 2 && typeof arguments[1] === "function") {
136+
var callback = arguments[1];
137+
callback();
138+
}
139+
},
140+
ready: function ready(fn, req) {
141+
var options = context.options;
142+
if(context.state) return fn(context.webpackStats);
143+
if(!options.noInfo && !options.quiet)
144+
options.log("webpack: wait until bundle finished: " + (req.url || fn.name));
145+
context.callbacks.push(fn);
146+
},
147+
startWatch: function() {
148+
var options = context.options;
149+
var compiler = context.compiler;
150+
// start watching
151+
if(!options.lazy) {
152+
var watching = compiler.watch(options.watchOptions, function(err) {
153+
if(err) throw err;
154+
});
155+
context.watching = watching;
156+
} else {
157+
context.state = true;
158+
}
159+
},
160+
rebuild: function rebuild() {
161+
if(context.state) {
162+
context.state = false;
163+
context.compiler.run(function(err) {
164+
if(err) throw err;
165+
});
166+
} else {
167+
context.forceRebuild = true;
168+
}
169+
},
170+
handleRequest: function(filename, processRequest, req) {
171+
// in lazy mode, rebuild on bundle request
172+
if(context.options.lazy && (!context.options.filename || context.options.filename.test(filename)))
173+
share.rebuild();
174+
if(HASH_REGEXP.test(filename)) {
175+
try {
176+
if(context.fs.statSync(filename).isFile()) {
177+
processRequest();
178+
return;
179+
}
180+
} catch(e) {
181+
}
182+
}
183+
share.ready(processRequest, req);
184+
},
185+
waitUntilValid: function(callback) {
186+
callback = callback || function() {};
187+
share.ready(callback, {});
188+
},
189+
invalidate: function(callback) {
190+
callback = callback || function() {};
191+
if(context.watching) {
192+
share.ready(callback, {});
193+
context.watching.invalidate();
194+
} else {
195+
callback();
196+
}
197+
},
198+
close: function(callback) {
199+
callback = callback || function() {};
200+
if(context.watching) context.watching.close(callback);
201+
else callback();
202+
}
203+
};
204+
share.setOptions(context.options);
205+
share.setFs(context.compiler);
206+
207+
context.compiler.plugin("done", share.compilerDone);
208+
context.compiler.plugin("invalid", share.compilerInvalid);
209+
context.compiler.plugin("watch-run", share.compilerInvalid);
210+
context.compiler.plugin("run", share.compilerInvalid);
211+
212+
share.startWatch();
213+
return share;
214+
};

0 commit comments

Comments
 (0)