UNPKG

8.24 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 return new (P || (P = Promise))(function (resolve, reject) {
4 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
7 step((generator = generator.apply(thisArg, _arguments || [])).next());
8 });
9};
10var __importDefault = (this && this.__importDefault) || function (mod) {
11 return (mod && mod.__esModule) ? mod : { "default": mod };
12};
13Object.defineProperty(exports, "__esModule", { value: true });
14const webpack_1 = __importDefault(require("webpack"));
15const path_1 = require("path");
16const lodash_1 = require("lodash");
17const fs_1 = require("fs");
18const handlebars_1 = require("handlebars");
19const js_string_escape_1 = __importDefault(require("js-string-escape"));
20const fs_extra_1 = require("fs-extra");
21handlebars_1.registerHelper('js-string-escape', js_string_escape_1.default);
22const entryTemplate = handlebars_1.compile(`
23if (typeof document !== 'undefined') {
24 {{#if publicAssetURL}}
25 __webpack_public_path__ = '{{js-string-escape publicAssetURL}}';
26 {{else}}
27 {{!
28 locate the webpack lazy loaded chunks relative to the currently executing
29 script. The last <script> in DOM should be us, assuming that we are being
30 synchronously loaded, which is the normal thing to do. If people are doing
31 weirder things than that, they may need to explicitly set a publicAssetURL
32 instead.
33 }}
34 __webpack_public_path__ = (function(){
35 var scripts = document.querySelectorAll('script');
36 return scripts[scripts.length - 1].src.replace(/\\/[^/]*$/, '/');
37 })();
38 {{/if}}
39}
40
41module.exports = (function(){
42 var d = _eai_d;
43 var r = _eai_r;
44 window.emberAutoImportDynamic = function(specifier) {
45 return r('_eai_dyn_' + specifier);
46 };
47 {{#each staticImports as |module|}}
48 d('{{js-string-escape module.specifier}}', [], function() { return require('{{js-string-escape module.entrypoint}}'); });
49 {{/each}}
50 {{#each dynamicImports as |module|}}
51 d('_eai_dyn_{{js-string-escape module.specifier}}', [], function() { return import('{{js-string-escape module.entrypoint}}'); });
52 {{/each}}
53})();
54`);
55// this goes in a file by itself so we can tell webpack not to parse it. That
56// allows us to grab the "require" and "define" from our enclosing scope without
57// webpack messing with them.
58//
59// It's important that we're using our enclosing scope and not jumping directly
60// to window.require (which would be easier), because the entire Ember app may be
61// inside a closure with a "require" that isn't the same as "window.require".
62const loader = `
63window._eai_r = require;
64window._eai_d = define;
65`;
66class WebpackBundler {
67 constructor(bundles, environment, extraWebpackConfig, consoleWrite, publicAssetURL, tempArea) {
68 this.consoleWrite = consoleWrite;
69 this.publicAssetURL = publicAssetURL;
70 // resolve the real path, because we're going to do path comparisons later
71 // that could fail if this is not canonical.
72 tempArea = fs_1.realpathSync(tempArea);
73 this.stagingDir = path_1.join(tempArea, 'staging');
74 fs_extra_1.ensureDirSync(this.stagingDir);
75 this.outputDir = path_1.join(tempArea, 'output');
76 fs_extra_1.ensureDirSync(this.outputDir);
77 let entry = {};
78 bundles.names.forEach(bundle => {
79 entry[bundle] = [path_1.join(this.stagingDir, 'l.js'), path_1.join(this.stagingDir, `${bundle}.js`)];
80 });
81 let config = {
82 mode: environment === 'production' ? 'production' : 'development',
83 entry,
84 output: {
85 path: this.outputDir,
86 filename: `chunk.[chunkhash].js`,
87 chunkFilename: `chunk.[chunkhash].js`,
88 libraryTarget: 'var',
89 library: '__ember_auto_import__'
90 },
91 optimization: {
92 splitChunks: {
93 chunks: 'all'
94 }
95 },
96 module: {
97 noParse: (file) => file === path_1.join(this.stagingDir, 'l.js'),
98 rules: []
99 },
100 };
101 if (extraWebpackConfig) {
102 mergeConfig(config, extraWebpackConfig);
103 }
104 this.webpack = webpack_1.default(config);
105 }
106 build(bundleDeps) {
107 return __awaiter(this, void 0, void 0, function* () {
108 for (let [bundle, deps] of bundleDeps.entries()) {
109 this.writeEntryFile(bundle, deps);
110 }
111 this.writeLoaderFile();
112 let stats = yield this.runWebpack();
113 return this.summarizeStats(stats);
114 });
115 }
116 summarizeStats(_stats) {
117 let stats = _stats.toJson();
118 let output = {
119 entrypoints: new Map(),
120 lazyAssets: [],
121 dir: this.outputDir
122 };
123 let nonLazyAssets = new Set();
124 for (let id of Object.keys(stats.entrypoints)) {
125 let entrypoint = stats.entrypoints[id];
126 output.entrypoints.set(id, entrypoint.assets);
127 entrypoint.assets.forEach((asset) => nonLazyAssets.add(asset));
128 }
129 for (let asset of stats.assets) {
130 if (!nonLazyAssets.has(asset.name)) {
131 output.lazyAssets.push(asset.name);
132 }
133 }
134 return output;
135 }
136 writeEntryFile(name, deps) {
137 fs_1.writeFileSync(path_1.join(this.stagingDir, `${name}.js`), entryTemplate({
138 staticImports: deps.staticImports,
139 dynamicImports: deps.dynamicImports,
140 publicAssetURL: this.publicAssetURL
141 }));
142 }
143 writeLoaderFile() {
144 fs_1.writeFileSync(path_1.join(this.stagingDir, `l.js`), loader);
145 }
146 runWebpack() {
147 return __awaiter(this, void 0, void 0, function* () {
148 return new Promise((resolve, reject) => {
149 this.webpack.run((err, stats) => {
150 if (err) {
151 this.consoleWrite(stats.toString());
152 reject(err);
153 return;
154 }
155 if (stats.hasErrors()) {
156 this.consoleWrite(stats.toString());
157 reject(new Error('webpack returned errors to ember-auto-import'));
158 return;
159 }
160 if (stats.hasWarnings() || process.env.AUTO_IMPORT_VERBOSE) {
161 this.consoleWrite(stats.toString());
162 }
163 resolve(stats);
164 });
165 });
166 });
167 }
168}
169exports.default = WebpackBundler;
170function mergeConfig(dest, ...srcs) {
171 return lodash_1.mergeWith(dest, ...srcs, combine);
172}
173exports.mergeConfig = mergeConfig;
174function combine(objValue, srcValue, key) {
175 if (key === 'noParse') {
176 return eitherPattern(objValue, srcValue);
177 }
178 // arrays concat
179 if (Array.isArray(objValue)) {
180 return objValue.concat(srcValue);
181 }
182}
183// webpack configs have several places where they accept:
184// - RegExp
185// - [RegExp]
186// - (resource: string) => boolean
187// - string
188// - [string]
189// This function combines any of these with a logical OR.
190function eitherPattern(...patterns) {
191 let flatPatterns = lodash_1.flatten(patterns);
192 return function (resource) {
193 for (let pattern of flatPatterns) {
194 if (pattern instanceof RegExp) {
195 if (pattern.test(resource)) {
196 return true;
197 }
198 }
199 else if (typeof pattern === 'string') {
200 if (pattern === resource) {
201 return true;
202 }
203 }
204 else if (typeof pattern === 'function') {
205 if (pattern(resource)) {
206 return true;
207 }
208 }
209 }
210 return false;
211 };
212}
213//# sourceMappingURL=webpack.js.map
\No newline at end of file