Skip to content

Commit 27dae4d

Browse files
committed
Bundler: generate bundleInfo, remove duplicated TS boilerplate
1 parent d3267ff commit 27dae4d

3 files changed

Lines changed: 154 additions & 10 deletions

File tree

build/gulpfile.common.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ function toBundleStream(bundledFileHeader, bundles) {
128128
* - resources (svg, etc.)
129129
* - loaderConfig
130130
* - header (basically the Copyright treatment)
131+
* - bundleInfo (boolean - emit bundleInfo.json file)
131132
* - out (out folder name)
132133
*/
133134
exports.optimizeTask = function(opts) {
@@ -141,6 +142,7 @@ exports.optimizeTask = function(opts) {
141142
return function() {
142143
var bundlesStream = es.through(); // this stream will contain the bundled files
143144
var resourcesStream = es.through(); // this stream will contain the resources
145+
var bundleInfoStream = es.through(); // this stream will contain bundleInfo.json
144146

145147
bundle.bundle(entryPoints, loaderConfig, function(err, result) {
146148
if (err) { return bundlesStream.emit('error', JSON.stringify(err)); }
@@ -155,6 +157,16 @@ exports.optimizeTask = function(opts) {
155157
filteredResources.push('!' + resource);
156158
});
157159
gulp.src(filteredResources, { base: 'out-build' }).pipe(resourcesStream);
160+
161+
var bundleInfoArray = [];
162+
if (opts.bundleInfo) {
163+
bundleInfoArray.push(new File({
164+
path: 'bundleInfo.json',
165+
base: '.',
166+
contents: new Buffer(JSON.stringify(result.bundleData, null, '\t'))
167+
}));
168+
}
169+
es.readArray(bundleInfoArray).pipe(bundleInfoStream);
158170
});
159171

160172
var otherSourcesStream = es.through();
@@ -175,7 +187,8 @@ exports.optimizeTask = function(opts) {
175187
loader(bundledFileHeader),
176188
bundlesStream,
177189
otherSourcesStream,
178-
resourcesStream
190+
resourcesStream,
191+
bundleInfoStream
179192
);
180193

181194
return result

build/lib/bundle.js

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ function bundle(entryPoints, config, callback) {
2323
loader.config(config);
2424
loader(Object.keys(entryPointsMap), function () {
2525
var modules = loader.getBuildInfo();
26-
var resultFiles = emitEntryPoints(modules, entryPointsMap);
26+
var partialResult = emitEntryPoints(modules, entryPointsMap);
2727
var cssInlinedResources = loader('vs/css').getInlinedResources();
2828
callback(null, {
29-
files: resultFiles,
30-
cssInlinedResources: cssInlinedResources
29+
files: partialResult.files,
30+
cssInlinedResources: cssInlinedResources,
31+
bundleData: partialResult.bundleData
3132
});
3233
}, function (err) { return callback(err, null); });
3334
}
@@ -44,6 +45,10 @@ function emitEntryPoints(modules, entryPoints) {
4445
var sortedModules = topologicalSort(modulesGraph);
4546
var result = [];
4647
var usedPlugins = {};
48+
var bundleData = {
49+
graph: modulesGraph,
50+
bundles: {}
51+
};
4752
Object.keys(entryPoints).forEach(function (moduleToBundle) {
4853
var info = entryPoints[moduleToBundle];
4954
var rootNodes = [moduleToBundle].concat(info.include || []);
@@ -58,6 +63,7 @@ function emitEntryPoints(modules, entryPoints) {
5863
var includedModules = sortedModules.filter(function (module) {
5964
return allDependencies[module];
6065
});
66+
bundleData.bundles[moduleToBundle] = includedModules;
6167
var res = emitEntryPoint(modulesMap, modulesGraph, moduleToBundle, includedModules);
6268
result = result.concat(res.files);
6369
for (var pluginName in res.usedPlugins) {
@@ -79,7 +85,60 @@ function emitEntryPoints(modules, entryPoints) {
7985
plugin.finishBuild(write);
8086
}
8187
});
82-
return result;
88+
return {
89+
files: removeDuplicateTSBoilerplate(result),
90+
bundleData: bundleData
91+
};
92+
}
93+
function removeDuplicateTSBoilerplate(destFiles) {
94+
// Taken from typescript compiler => emitFiles
95+
var BOILERPLATE = [
96+
{ start: /^var __extends/, end: /^};$/ },
97+
{ start: /^var __assign/, end: /^};$/ },
98+
{ start: /^var __decorate/, end: /^};$/ },
99+
{ start: /^var __metadata/, end: /^};$/ },
100+
{ start: /^var __param/, end: /^};$/ },
101+
{ start: /^var __awaiter/, end: /^};$/ },
102+
];
103+
destFiles.forEach(function (destFile) {
104+
var SEEN_BOILERPLATE = [];
105+
destFile.sources.forEach(function (source) {
106+
var lines = source.contents.split(/\r\n|\n|\r/);
107+
var newLines = [];
108+
var IS_REMOVING_BOILERPLATE = false, END_BOILERPLATE;
109+
for (var i = 0; i < lines.length; i++) {
110+
var line = lines[i];
111+
if (IS_REMOVING_BOILERPLATE) {
112+
newLines.push('');
113+
if (END_BOILERPLATE.test(line)) {
114+
IS_REMOVING_BOILERPLATE = false;
115+
}
116+
}
117+
else {
118+
for (var j = 0; j < BOILERPLATE.length; j++) {
119+
var boilerplate = BOILERPLATE[j];
120+
if (boilerplate.start.test(line)) {
121+
if (SEEN_BOILERPLATE[j]) {
122+
IS_REMOVING_BOILERPLATE = true;
123+
END_BOILERPLATE = boilerplate.end;
124+
}
125+
else {
126+
SEEN_BOILERPLATE[j] = true;
127+
}
128+
}
129+
}
130+
if (IS_REMOVING_BOILERPLATE) {
131+
newLines.push('');
132+
}
133+
else {
134+
newLines.push(line);
135+
}
136+
}
137+
}
138+
source.contents = newLines.join('\n');
139+
});
140+
});
141+
return destFiles;
83142
}
84143
function emitEntryPoint(modulesMap, deps, entryPoint, includedModules) {
85144
var mainResult = {

build/lib/bundle.ts

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,20 @@ export interface IConcatFile {
7070
sources: IFile[];
7171
}
7272

73+
export interface IBundleData {
74+
graph: IGraph;
75+
bundles: {[moduleId:string]:string[];};
76+
}
77+
7378
export interface IBundleResult {
7479
files: IConcatFile[];
7580
cssInlinedResources: string[];
81+
bundleData: IBundleData;
82+
}
83+
84+
interface IPartialBundleResult {
85+
files: IConcatFile[];
86+
bundleData: IBundleData;
7687
}
7788

7889
export interface ILoaderConfig {
@@ -100,16 +111,17 @@ export function bundle(entryPoints:IEntryPoint[], config:ILoaderConfig, callback
100111

101112
loader(Object.keys(entryPointsMap), () => {
102113
let modules = <IBuildModuleInfo[]>loader.getBuildInfo();
103-
let resultFiles = emitEntryPoints(modules, entryPointsMap);
114+
let partialResult = emitEntryPoints(modules, entryPointsMap);
104115
let cssInlinedResources = loader('vs/css').getInlinedResources();
105116
callback(null, {
106-
files: resultFiles,
107-
cssInlinedResources: cssInlinedResources
117+
files: partialResult.files,
118+
cssInlinedResources: cssInlinedResources,
119+
bundleData: partialResult.bundleData
108120
});
109121
}, (err) => callback(err, null));
110122
}
111123

112-
function emitEntryPoints(modules:IBuildModuleInfo[], entryPoints:IEntryPointMap): IConcatFile[] {
124+
function emitEntryPoints(modules:IBuildModuleInfo[], entryPoints:IEntryPointMap): IPartialBundleResult {
113125
let modulesMap: IBuildModuleInfoMap = {};
114126
modules.forEach((m:IBuildModuleInfo) => {
115127
modulesMap[m.id] = m;
@@ -124,6 +136,10 @@ function emitEntryPoints(modules:IBuildModuleInfo[], entryPoints:IEntryPointMap)
124136

125137
let result: IConcatFile[] = [];
126138
let usedPlugins: IPluginMap = {};
139+
let bundleData:IBundleData = {
140+
graph: modulesGraph,
141+
bundles: {}
142+
};
127143

128144
Object.keys(entryPoints).forEach((moduleToBundle:string) => {
129145
let info = entryPoints[moduleToBundle];
@@ -142,6 +158,8 @@ function emitEntryPoints(modules:IBuildModuleInfo[], entryPoints:IEntryPointMap)
142158
return allDependencies[module];
143159
});
144160

161+
bundleData.bundles[moduleToBundle] = includedModules;
162+
145163
let res = emitEntryPoint(modulesMap, modulesGraph, moduleToBundle, includedModules);
146164

147165
result = result.concat(res.files);
@@ -166,7 +184,61 @@ function emitEntryPoints(modules:IBuildModuleInfo[], entryPoints:IEntryPointMap)
166184
}
167185
});
168186

169-
return result;
187+
return {
188+
files: removeDuplicateTSBoilerplate(result),
189+
bundleData: bundleData
190+
};
191+
}
192+
193+
function removeDuplicateTSBoilerplate(destFiles:IConcatFile[]):IConcatFile[] {
194+
// Taken from typescript compiler => emitFiles
195+
let BOILERPLATE = [
196+
{ start: /^var __extends/, end: /^};$/ },
197+
{ start: /^var __assign/, end: /^};$/ },
198+
{ start: /^var __decorate/, end: /^};$/ },
199+
{ start: /^var __metadata/, end: /^};$/ },
200+
{ start: /^var __param/, end: /^};$/ },
201+
{ start: /^var __awaiter/, end: /^};$/ },
202+
];
203+
204+
destFiles.forEach((destFile) => {
205+
let SEEN_BOILERPLATE = [];
206+
destFile.sources.forEach((source) => {
207+
let lines = source.contents.split(/\r\n|\n|\r/);
208+
let newLines: string[] = [];
209+
let IS_REMOVING_BOILERPLATE = false, END_BOILERPLATE: RegExp;
210+
211+
for (let i = 0; i < lines.length; i++) {
212+
let line = lines[i];
213+
if (IS_REMOVING_BOILERPLATE) {
214+
newLines.push('');
215+
if (END_BOILERPLATE.test(line)) {
216+
IS_REMOVING_BOILERPLATE = false;
217+
}
218+
} else {
219+
for (let j = 0; j < BOILERPLATE.length; j++) {
220+
let boilerplate = BOILERPLATE[j];
221+
if (boilerplate.start.test(line)) {
222+
if (SEEN_BOILERPLATE[j]) {
223+
IS_REMOVING_BOILERPLATE = true;
224+
END_BOILERPLATE = boilerplate.end;
225+
} else {
226+
SEEN_BOILERPLATE[j] = true;
227+
}
228+
}
229+
}
230+
if (IS_REMOVING_BOILERPLATE) {
231+
newLines.push('');
232+
} else {
233+
newLines.push(line);
234+
}
235+
}
236+
}
237+
source.contents = newLines.join('\n');
238+
});
239+
});
240+
241+
return destFiles;
170242
}
171243

172244
interface IPluginMap {

0 commit comments

Comments
 (0)