UNPKG

6.41 kBJavaScriptView Raw
1var winston = require('winston'),
2 order = require("../graph/order"),
3 transpile = require("../graph/transpile"),
4 minifyGraph = require("../graph/minify"),
5 pluck = require("../graph/pluck"),
6 makeBundle = require("../bundle/make_bundle"),
7 nameBundle = require("../bundle/name"),
8 flattenBundle = require("../bundle/flatten"),
9 makeBundlesConfig = require("../bundle/make_bundles_config"),
10 splitByBuildType = require("../bundle/split_by_build_type"),
11 addStealToBundle = require("../bundle/add_steal"),
12 _ = require("lodash"),
13 hasES6 = require("../graph/has_es6"),
14 clean = require("../graph/clean"),
15 addTraceurRuntime = require("../bundle/add_traceur_runtime"),
16 makeConfiguration = require("../configuration/make"),
17 splitGraphByModuleNames = require("../graph/split"),
18 getBundleForOnly = require("../bundle/get_for_only"),
19 findBundles = require("../loader/find_bundle"),
20 through = require("through2"),
21 bundleDepth = require("../bundle/depth"),
22 markBundlesDirty = require("../bundle/mark_as_dirty"),
23 unbundle = require("../graph/unbundle");
24
25
26module.exports = function(){
27
28 return through.obj(function(data, enc, done){
29 try {
30 var buildResult = multiBuild(data);
31 done(null, buildResult);
32 } catch(err) {
33 done(err);
34 }
35 });
36
37 function multiBuild(data){
38 var dependencyGraph = data.graph,
39 options = data.options,
40 config = data.config,
41 // the apps we are building
42 mains = Array.isArray(config.main) ? config.main.slice(0) : [data.loader.main],
43 configuration = makeConfiguration(data.loader, data.buildLoader, options);
44
45 // Remove @config so it is not transpiled. It is a global,
46 // but we will want it to run ASAP.
47 var stealconfig = pluck(dependencyGraph,data.loader.configMain ||"@config");
48
49 // Transpile the source to AMD
50 options.sourceMapPath = configuration.bundlesPath;
51 transpile(stealconfig, "amd", options, data);
52
53 // Remove steal dev from production builds.
54 pluck(dependencyGraph,"@dev");
55
56 // Adds an `order` property to each `Node` so we know which modules.
57 // The lower the number the lower on the dependency tree it is.
58 // For example, jQuery might have `order: 0`.
59 mains.forEach(function(moduleName){
60 order(dependencyGraph, moduleName);
61 });
62
63 findBundles(data.loader).forEach(function(moduleName){
64 order(dependencyGraph, moduleName);
65 });
66
67 // Clean development code if the option was passed
68 if(options.removeDevelopmentCode) {
69 clean(dependencyGraph, options);
70 }
71
72 // Transpile each module to amd. Eventually, production builds
73 // should be able to work without steal.js.
74 winston.info('Transpiling...');
75 transpile(dependencyGraph, "amd", options, data);
76
77 // Minify every file in the graph
78 if(options.minify) {
79 winston.info('Minifying...');
80 minifyGraph(dependencyGraph, options);
81 minifyGraph(stealconfig, options);
82 }
83
84 // Get unbundled graphs, these are graphs of modules that are marked
85 // to not be bundled, they will be put into their own bundles later.
86 var unbundledGraphs = unbundle(dependencyGraph);
87
88 // Split the graph into two smaller graphs. One will contain the
89 // "mains" and their dependencies that need to be loaded right away.
90 // The other will will be the bundles that are progressively loaded.
91 var splitGraphs = splitGraphByModuleNames(dependencyGraph, mains),
92 mainsGraph = splitGraphs["with"],
93 bundledGraph = splitGraphs.without;
94
95 winston.info('Calculating main bundle(s)...');
96 // Put everything into unique bundle graphs that have no waste.
97 var mainBundles = makeBundle(mainsGraph);
98 // Combine bundles to reduce the number of total bundles that will need to be loaded
99 winston.info('Flattening main bundle(s)...');
100 flattenBundle(mainBundles, bundleDepth(config, options, true));
101 // Break up bundles by buildType
102 var splitMainBundles = splitByBuildType(mainBundles);
103
104 var splitBundles = [];
105 if(!_.isEmpty(bundledGraph)) {
106 winston.info('Calculating progressively loaded bundle(s)...');
107 // Put everything into unique bundle graphs that have no waste.
108 var bundles = makeBundle(bundledGraph);
109 // Combine bundles to reduce the number of total bundles that will need to be loaded
110 winston.info('Flattening progressively loaded bundle(s)...');
111 flattenBundle(bundles, bundleDepth(config, options));
112 // Break up bundles by buildType
113 splitBundles = splitByBuildType(bundles);
114 }
115
116 // Every mainBundle needs to have @config and bundle configuration to know
117 // where everything is. Lets get those main bundles here while there is less to go through.
118
119 var mainJSBundles = mains.map(function(main){
120 return getBundleForOnly(splitMainBundles,main,"js");
121 });
122
123 // Create unbundled bundles, for modules marked as sideBundle: true
124 var unbundledBundles = unbundledGraphs.reduce(function(bundles, graph){
125 bundles.push.apply(bundles, makeBundle(graph));
126 return bundles;
127 }, []);
128 unbundledBundles = splitByBuildType(unbundledBundles);
129
130 // Combine all bundles
131 var allBundles = splitMainBundles.concat(splitBundles);
132 allBundles = allBundles.concat.apply(allBundles, unbundledBundles);
133
134 // Name each bundle so we know what to call the bundle.
135 nameBundle(allBundles);
136
137 // Create a lookup object of the main bundle names so that they are
138 // excluded from the Bundles config
139 var mainJSBundleNames = {};
140 mainJSBundles.forEach(function(mainJSBundle){
141 mainJSBundleNames[mainJSBundle.name] = true;
142 });
143
144 // Add @config and the bundleConfigNode to each main
145 mainJSBundles.forEach(function(mainJSBundle){
146 [].unshift.apply(mainJSBundle.nodes, stealconfig );
147 // Make config JS code so System knows where to look for bundles.
148 var configNode = makeBundlesConfig(allBundles, configuration, mainJSBundle, {
149 excludedBundles: mainJSBundleNames
150 });
151 mainJSBundle.nodes.unshift(configNode);
152
153 if(options.bundleSteal) {
154 addStealToBundle({
155 bundle: mainJSBundle,
156 main: mainJSBundle.bundles[0],
157 configuration: configuration,
158 bundlePromisePolyfill: options.bundlePromisePolyfill
159 });
160 }
161 // Traceur code requires a runtime.
162 var hasES6modules = hasES6(dependencyGraph);
163 if( hasES6modules ) {
164 addTraceurRuntime(mainJSBundle);
165 }
166 });
167
168 // Mark bundles that are dirty so that they will be written to the file
169 // system.
170 markBundlesDirty(allBundles, data);
171
172 return _.extend({}, data, {
173 bundles: allBundles,
174 configuration: configuration
175 });
176 }
177};