forked from derbyjs/racer-bundle
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
112 lines (96 loc) · 3.6 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
var fs = require('fs');
var browserify = require('browserify');
var watchify = require('watchify');
var uglify = require('uglify-es');
var convertSourceMap = require('convert-source-map');
var anymatch = require('anymatch');
var util;
module.exports = function(racer) {
var Backend = racer.Backend || racer.Store;
Backend.prototype.bundle = bundle;
util = racer.util;
};
function bundle(file, options, cb) {
if (typeof options === 'function') {
cb = options;
options = null;
}
options || (options = {});
options.debug = options.sourcemaps;
// enable fullPaths to use https://github.com/hughsk/disc
// options.fullPaths = true;
var minify = (options.minify == null) ? util.isProduction : options.minify;
// These objects need to be defined otherwise watchify disables its cache
options.cache = {};
options.packageCache = {};
var b = browserify(options);
this.emit('bundle', b);
b.add(file);
// If onRebundle is defined, watch the bundle for changes
if (options.onRebundle) {
var w = watchify(b, {
delay: 100,
});
w.on('log', function (msg) {
console.log(file + ' bundled:', msg);
});
var ignore = (options.ignore == null) ? [] : options.ignore
// Chokidar/watchify provide the realpath's of files as their ids, so we
// add any realpath values that don't match the provided filepath's.
ignore.forEach(function(filepath) {
var realpath = fs.realpathSync(filepath);
if (realpath !== filepath) ignore.push(realpath);
});
var matchIgnorePaths = anymatch(ignore)
// This gets fired every time a dependent file is changed
w.on('update', function(ids) {
console.log('Files changed:', ids.toString());
// If all the changed files are ignoreable, return before bundling
if (ids.every(matchIgnorePaths)) {
return console.log('Ignoring update')
}
callBundle(this, options, options.onRebundle);
});
callBundle(w, options, cb);
} else {
callBundle(b, options, cb);
}
}
function callBundle(b, options, cb) {
b.bundle(function(err, buffer) {
if (err) return cb(err);
// Extract the source map, which Browserify includes as a comment
var source = buffer.toString('utf8');
if (options.sourcemaps) {
var map = convertSourceMap.fromSource(source).toJSON();
source = convertSourceMap.removeComments(source);
}
if (!options.minify) return cb(null, source, map);
var uglifyOptions = {
compress: true,
mangle: true
}
if (options.sourcemaps) {
var inSourceMap = JSON.parse(map);
uglifyOptions.inSourceMap = inSourceMap;
uglifyOptions.outSourceMap = 'map';
}
var result = uglify.minify(source, uglifyOptions);
// If inSourceMap is a string it is assumed to be a filename, but passing in
// as an object avoids the need to make a file
if (options.sourcemaps) {
var mapObject = JSON.parse(result.map);
// Uglify doesn't include the source content in the map, so copy over from
// the map that browserify generates. However, before doing this, we must
// first remove any empty sourceContent items since UglifyJS ignores those
// files when populating the outSourceMap.sources array.
mapObject.sourcesContent = inSourceMap.sourcesContent.filter(isNotEmptyString)
if (mapObject.sources.length != mapObject.sourcesContent.length) {
console.error('Invalid sourcemap detected. sources.length does not match sourcesContent.length')
}
var map = JSON.stringify(mapObject);
}
cb(null, result.code, map);
});
}
function isNotEmptyString(str) { return str !== '' }