UNPKG

3.05 kBJavaScriptView Raw
1var path = require("path");
2var fs = require("fs-extra");
3var through = require("through2");
4var denodeify = require("pdenodeify");
5var concat = require("lodash/concat");
6var includes = require("lodash/includes");
7var isString = require("lodash/isString");
8var isJavaScriptBundle = require("../bundle/is_js_bundle");
9
10var outputFile = denodeify(fs.outputFile);
11
12module.exports = function() {
13 return through.obj(function(data, enc, next) {
14 var promise = canWriteManifest(data.options) ?
15 writeBundleManifest(data) :
16 Promise.resolve(data);
17
18 promise
19 .then(function(result) {
20 next(null, result);
21 })
22 .catch(next);
23 });
24};
25
26/**
27 * Whether the option to generate the manifest was set
28 * @param {Object} options - The build options object
29 */
30function canWriteManifest(options) {
31 return options.bundleManifest === true || isString(options.bundleManifest);
32}
33
34function writeBundleManifest(data) {
35 var manifest = {};
36
37 var entryPointBundles = concat(
38 data.mains,
39 data.loader.bundle
40 );
41
42 entryPointBundles.forEach(function(bundleName) {
43 manifest[bundleName] = getSharedBundlesOf(
44 bundleName,
45 data.loader.baseURL,
46 data.bundles,
47 data.mains
48 );
49 });
50
51 // defaults to `dist/bundles.json`
52 var dest = isString(data.options.bundleManifest) ?
53 data.options.bundleManifest :
54 path.join(data.configuration.dest, "bundles.json");
55
56 // write the manifest file
57 return outputFile(
58 dest,
59 JSON.stringify(manifest, null, "\t")
60 ).then(function() {
61 return data;
62 });
63}
64
65/**
66 * A very simplified version of HTTP2 stream priorities
67 * Bundles with the lowest weight should be loaded first
68 *
69 * @param {Object} bundle - A bundle object
70 * @return {Number} 1 for css bundles, 2 for main JS bundles, 3 for shared bundles
71 */
72function getWeightOf(bundle) {
73 var isCss = bundle.buildType === "css";
74 var isMainBundle = bundle.bundles.length === 1;
75
76 if (isCss) {
77 return 1;
78 } else if (isMainBundle) {
79 return 2;
80 } else {
81 return 3;
82 }
83}
84
85/**
86 * Returns an object of shared bundles data
87 * @param {string} name - A bundle name
88 * @param {string} baseUrl - The loader's baseURL
89 * @param {Array} bundles - The bundles array created by the build process
90 * @param {Array} mains - The main entry point modules
91 * @return {Object} Each key is a shared bundle relative path and the value
92 * contains the `weight` and `type` of the bundle
93 */
94function getSharedBundlesOf(name, baseUrl, bundles, mains) {
95 var shared = {};
96 var normalize = require("normalize-path");
97 // this will ensure that we only add the main bundle if there is a single
98 // main; not a multi-main project.
99 var singleMain = mains.length === 1 && mains[0];
100
101 bundles.forEach(function(bundle) {
102 if (includes(bundle.bundles, name) ||
103 includes(bundle.bundles, singleMain)) {
104 var relative = normalize(
105 path.relative(
106 baseUrl.replace("file:", ""),
107 bundle.bundlePath
108 )
109 );
110
111 shared[relative] = {
112 weight: getWeightOf(bundle),
113 type: isJavaScriptBundle(bundle) ? "script" : "style"
114 };
115 }
116 });
117
118 return shared;
119}