UNPKG

27.9 kBJavaScriptView Raw
1"use strict";
2/**
3 * @license
4 * Copyright Google LLC All Rights Reserved.
5 *
6 * Use of this source code is governed by an MIT-style license that can be
7 * found in the LICENSE file at https://angular.io/license
8 */
9Object.defineProperty(exports, "__esModule", { value: true });
10exports.inlineLocales = exports.createI18nPlugins = exports.process = exports.setup = void 0;
11const core_1 = require("@babel/core");
12const template_1 = require("@babel/template");
13const cacache = require("cacache");
14const crypto_1 = require("crypto");
15const fs = require("fs");
16const path = require("path");
17const source_map_1 = require("source-map");
18const terser_1 = require("terser");
19const v8 = require("v8");
20const webpack_1 = require("webpack");
21const environment_options_1 = require("./environment-options");
22const { ConcatSource, OriginalSource, ReplaceSource, SourceMapSource } = webpack_1.sources;
23// If code size is larger than 500KB, consider lower fidelity but faster sourcemap merge
24const FAST_SOURCEMAP_THRESHOLD = 500 * 1024;
25let cachePath;
26let i18n;
27function setup(data) {
28 const options = Array.isArray(data)
29 ? v8.deserialize(Buffer.from(data))
30 : data;
31 cachePath = options.cachePath;
32 i18n = options.i18n;
33}
34exports.setup = setup;
35async function cachePut(content, key, integrity) {
36 if (cachePath && key) {
37 await cacache.put(cachePath, key, content, {
38 metadata: { integrity },
39 });
40 }
41}
42async function process(options) {
43 if (!options.cacheKeys) {
44 options.cacheKeys = [];
45 }
46 const result = { name: options.name };
47 if (options.integrityAlgorithm) {
48 // Store unmodified code integrity value -- used for SRI value replacement
49 result.integrity = generateIntegrityValue(options.integrityAlgorithm, options.code);
50 }
51 // Runtime chunk requires specialized handling
52 if (options.runtime) {
53 return { ...result, ...(await processRuntime(options)) };
54 }
55 const basePath = path.dirname(options.filename);
56 const filename = path.basename(options.filename);
57 const downlevelFilename = filename.replace(/\-(es20\d{2}|esnext)/, '-es5');
58 const downlevel = !options.optimizeOnly;
59 const sourceCode = options.code;
60 const sourceMap = options.map ? JSON.parse(options.map) : undefined;
61 let downlevelCode;
62 let downlevelMap;
63 if (downlevel) {
64 const { supportedBrowsers: targets = [] } = options;
65 // todo: revisit this in version 10, when we update our defaults browserslist
66 // Without this workaround bundles will not be downlevelled because Babel doesn't know handle to 'op_mini all'
67 // See: https://github.com/babel/babel/issues/11155
68 if (Array.isArray(targets) && targets.includes('op_mini all')) {
69 targets.push('ie_mob 11');
70 }
71 else if ('op_mini' in targets) {
72 targets['ie_mob'] = '11';
73 }
74 // Downlevel the bundle
75 const transformResult = await core_1.transformAsync(sourceCode, {
76 filename,
77 // using false ensures that babel will NOT search and process sourcemap comments (large memory usage)
78 // The types do not include the false option even though it is valid
79 // eslint-disable-next-line @typescript-eslint/no-explicit-any
80 inputSourceMap: false,
81 babelrc: false,
82 configFile: false,
83 presets: [
84 [
85 require.resolve('@babel/preset-env'),
86 {
87 // browserslist-compatible query or object of minimum environment versions to support
88 targets,
89 // modules aren't needed since the bundles use webpack's custom module loading
90 modules: false,
91 // 'transform-typeof-symbol' generates slower code
92 exclude: ['transform-typeof-symbol'],
93 },
94 ],
95 ],
96 plugins: [
97 createIifeWrapperPlugin(),
98 ...(options.replacements ? [createReplacePlugin(options.replacements)] : []),
99 ],
100 minified: environment_options_1.allowMinify && !!options.optimize,
101 compact: !environment_options_1.shouldBeautify && !!options.optimize,
102 sourceMaps: !!sourceMap,
103 });
104 if (!transformResult || !transformResult.code) {
105 throw new Error(`Unknown error occurred processing bundle for "${options.filename}".`);
106 }
107 downlevelCode = transformResult.code;
108 if (sourceMap && transformResult.map) {
109 // String length is used as an estimate for byte length
110 const fastSourceMaps = sourceCode.length > FAST_SOURCEMAP_THRESHOLD;
111 downlevelMap = await mergeSourceMaps(sourceCode, sourceMap, downlevelCode, transformResult.map, filename,
112 // When not optimizing, the sourcemaps are significantly less complex
113 // and can use the higher fidelity merge
114 !!options.optimize && fastSourceMaps);
115 }
116 }
117 if (downlevelCode) {
118 result.downlevel = await processBundle({
119 ...options,
120 code: downlevelCode,
121 map: downlevelMap,
122 filename: path.join(basePath, downlevelFilename),
123 isOriginal: false,
124 });
125 }
126 if (!result.original && !options.ignoreOriginal) {
127 result.original = await processBundle({
128 ...options,
129 isOriginal: true,
130 });
131 }
132 return result;
133}
134exports.process = process;
135async function mergeSourceMaps(inputCode, inputSourceMap, resultCode, resultSourceMap, filename, fast = false) {
136 // Webpack 5 terser sourcemaps currently fail merging with the high-quality method
137 if (fast) {
138 return mergeSourceMapsFast(inputSourceMap, resultSourceMap);
139 }
140 // SourceMapSource produces high-quality sourcemaps
141 // Final sourcemap will always be available when providing the input sourcemaps
142 const finalSourceMap = new SourceMapSource(resultCode, filename, resultSourceMap, inputCode, inputSourceMap, true).map();
143 return finalSourceMap;
144}
145async function mergeSourceMapsFast(first, second) {
146 const sourceRoot = first.sourceRoot;
147 const generator = new source_map_1.SourceMapGenerator();
148 // sourcemap package adds the sourceRoot to all position source paths if not removed
149 delete first.sourceRoot;
150 await source_map_1.SourceMapConsumer.with(first, null, (originalConsumer) => {
151 return source_map_1.SourceMapConsumer.with(second, null, (newConsumer) => {
152 newConsumer.eachMapping((mapping) => {
153 if (mapping.originalLine === null) {
154 return;
155 }
156 const originalPosition = originalConsumer.originalPositionFor({
157 line: mapping.originalLine,
158 column: mapping.originalColumn,
159 });
160 if (originalPosition.line === null ||
161 originalPosition.column === null ||
162 originalPosition.source === null) {
163 return;
164 }
165 generator.addMapping({
166 generated: {
167 line: mapping.generatedLine,
168 column: mapping.generatedColumn,
169 },
170 name: originalPosition.name || undefined,
171 original: {
172 line: originalPosition.line,
173 column: originalPosition.column,
174 },
175 source: originalPosition.source,
176 });
177 });
178 });
179 });
180 const map = generator.toJSON();
181 map.file = second.file;
182 map.sourceRoot = sourceRoot;
183 // Add source content if present
184 if (first.sourcesContent) {
185 // Source content array is based on index of sources
186 const sourceContentMap = new Map();
187 for (let i = 0; i < first.sources.length; i++) {
188 // make paths "absolute" so they can be compared (`./a.js` and `a.js` are equivalent)
189 sourceContentMap.set(path.resolve('/', first.sources[i]), i);
190 }
191 map.sourcesContent = [];
192 for (let i = 0; i < map.sources.length; i++) {
193 const contentIndex = sourceContentMap.get(path.resolve('/', map.sources[i]));
194 if (contentIndex === undefined) {
195 map.sourcesContent.push('');
196 }
197 else {
198 map.sourcesContent.push(first.sourcesContent[contentIndex]);
199 }
200 }
201 }
202 // Put the sourceRoot back
203 if (sourceRoot) {
204 first.sourceRoot = sourceRoot;
205 }
206 return map;
207}
208async function processBundle(options) {
209 const { optimize, isOriginal, code, map, filename: filepath, hiddenSourceMaps, cacheKeys = [], integrityAlgorithm, } = options;
210 const rawMap = typeof map === 'string' ? JSON.parse(map) : map;
211 const filename = path.basename(filepath);
212 let result;
213 if (rawMap) {
214 rawMap.file = filename;
215 }
216 if (optimize) {
217 result = await terserMangle(code, {
218 filename,
219 map: rawMap,
220 compress: !isOriginal,
221 ecma: isOriginal ? 2015 : 5,
222 });
223 }
224 else {
225 result = {
226 map: rawMap,
227 code,
228 };
229 }
230 let mapContent;
231 if (result.map) {
232 if (!hiddenSourceMaps) {
233 result.code += `\n//# sourceMappingURL=${filename}.map`;
234 }
235 mapContent = JSON.stringify(result.map);
236 await cachePut(mapContent, cacheKeys[isOriginal ? 1 /* OriginalMap */ : 3 /* DownlevelMap */]);
237 fs.writeFileSync(filepath + '.map', mapContent);
238 }
239 const fileResult = createFileEntry(filepath, result.code, mapContent, integrityAlgorithm);
240 await cachePut(result.code, cacheKeys[isOriginal ? 0 /* OriginalCode */ : 2 /* DownlevelCode */], fileResult.integrity);
241 fs.writeFileSync(filepath, result.code);
242 return fileResult;
243}
244async function terserMangle(code, options = {}) {
245 // Note: Investigate converting the AST instead of re-parsing
246 // estree -> terser is already supported; need babel -> estree/terser
247 // Mangle downlevel code
248 const minifyOutput = await terser_1.minify(options.filename ? { [options.filename]: code } : code, {
249 compress: environment_options_1.allowMinify && !!options.compress,
250 ecma: options.ecma || 5,
251 mangle: environment_options_1.allowMangle,
252 safari10: true,
253 format: {
254 ascii_only: true,
255 webkit: true,
256 beautify: environment_options_1.shouldBeautify,
257 wrap_func_args: false,
258 },
259 sourceMap: !!options.map &&
260 {
261 asObject: true,
262 // typings don't include asObject option
263 // eslint-disable-next-line @typescript-eslint/no-explicit-any
264 },
265 });
266 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
267 const outputCode = minifyOutput.code;
268 let outputMap;
269 if (options.map && minifyOutput.map) {
270 outputMap = await mergeSourceMaps(code, options.map, outputCode, minifyOutput.map, options.filename || '0', code.length > FAST_SOURCEMAP_THRESHOLD);
271 }
272 return { code: outputCode, map: outputMap };
273}
274function createFileEntry(filename, code, map, integrityAlgorithm) {
275 return {
276 filename: filename,
277 size: Buffer.byteLength(code),
278 integrity: integrityAlgorithm && generateIntegrityValue(integrityAlgorithm, code),
279 map: !map
280 ? undefined
281 : {
282 filename: filename + '.map',
283 size: Buffer.byteLength(map),
284 },
285 };
286}
287function generateIntegrityValue(hashAlgorithm, code) {
288 return hashAlgorithm + '-' + crypto_1.createHash(hashAlgorithm).update(code).digest('base64');
289}
290// The webpack runtime chunk is already ES5.
291// However, two variants are still needed due to lazy routing and SRI differences
292// NOTE: This should eventually be a babel plugin
293async function processRuntime(options) {
294 let originalCode = options.code;
295 let downlevelCode = options.code;
296 // Replace integrity hashes with updated values
297 if (options.integrityAlgorithm && options.runtimeData) {
298 for (const data of options.runtimeData) {
299 if (!data.integrity) {
300 continue;
301 }
302 if (data.original && data.original.integrity) {
303 originalCode = originalCode.replace(data.integrity, data.original.integrity);
304 }
305 if (data.downlevel && data.downlevel.integrity) {
306 downlevelCode = downlevelCode.replace(data.integrity, data.downlevel.integrity);
307 }
308 }
309 }
310 // Adjust lazy loaded scripts to point to the proper variant
311 // Extra spacing is intentional to align source line positions
312 downlevelCode = downlevelCode.replace(/"\-(es20\d{2}|esnext)\./, ' "-es5.');
313 return {
314 original: await processBundle({
315 ...options,
316 code: originalCode,
317 isOriginal: true,
318 }),
319 downlevel: await processBundle({
320 ...options,
321 code: downlevelCode,
322 filename: options.filename.replace(/\-(es20\d{2}|esnext)/, '-es5'),
323 isOriginal: false,
324 }),
325 };
326}
327function createReplacePlugin(replacements) {
328 return {
329 visitor: {
330 StringLiteral(path) {
331 for (const replacement of replacements) {
332 if (path.node.value === replacement[0]) {
333 path.node.value = replacement[1];
334 }
335 }
336 },
337 },
338 };
339}
340function createIifeWrapperPlugin() {
341 return {
342 visitor: {
343 Program: {
344 exit(path) {
345 // Save existing body and directives
346 const { body, directives } = path.node;
347 // Clear out body and directives for wrapper
348 path.node.body = [];
349 path.node.directives = [];
350 // Create the wrapper - "(function() { ... })();"
351 const wrapper = core_1.types.expressionStatement(core_1.types.callExpression(core_1.types.parenthesizedExpression(core_1.types.functionExpression(undefined, [], core_1.types.blockStatement(body, directives))), []));
352 // Insert the wrapper
353 path.pushContainer('body', wrapper);
354 },
355 },
356 },
357 };
358}
359const USE_LOCALIZE_PLUGINS = false;
360async function createI18nPlugins(locale, translation, missingTranslation, shouldInline, localeDataContent) {
361 const plugins = [];
362 const localizeDiag = await Promise.resolve().then(() => require('@angular/localize/src/tools/src/diagnostics'));
363 const diagnostics = new localizeDiag.Diagnostics();
364 if (shouldInline) {
365 const es2015 = await Promise.resolve().then(() => require('@angular/localize/src/tools/src/translate/source_files/es2015_translate_plugin'));
366 plugins.push(
367 // eslint-disable-next-line @typescript-eslint/no-explicit-any
368 es2015.makeEs2015TranslatePlugin(diagnostics, (translation || {}), {
369 missingTranslation: translation === undefined ? 'ignore' : missingTranslation,
370 }));
371 const es5 = await Promise.resolve().then(() => require('@angular/localize/src/tools/src/translate/source_files/es5_translate_plugin'));
372 plugins.push(
373 // eslint-disable-next-line @typescript-eslint/no-explicit-any
374 es5.makeEs5TranslatePlugin(diagnostics, (translation || {}), {
375 missingTranslation: translation === undefined ? 'ignore' : missingTranslation,
376 }));
377 }
378 const inlineLocale = await Promise.resolve().then(() => require('@angular/localize/src/tools/src/translate/source_files/locale_plugin'));
379 plugins.push(inlineLocale.makeLocalePlugin(locale));
380 if (localeDataContent) {
381 plugins.push({
382 visitor: {
383 Program(path) {
384 path.unshiftContainer('body', template_1.default.ast(localeDataContent));
385 },
386 },
387 });
388 }
389 return { diagnostics, plugins };
390}
391exports.createI18nPlugins = createI18nPlugins;
392const localizeName = '$localize';
393async function inlineLocales(options) {
394 var _a;
395 if (!i18n || i18n.inlineLocales.size === 0) {
396 return { file: options.filename, diagnostics: [], count: 0 };
397 }
398 if (i18n.flatOutput && i18n.inlineLocales.size > 1) {
399 throw new Error('Flat output is only supported when inlining one locale.');
400 }
401 const hasLocalizeName = options.code.includes(localizeName);
402 if (!hasLocalizeName && !options.setLocale) {
403 return inlineCopyOnly(options);
404 }
405 let ast;
406 try {
407 ast = core_1.parseSync(options.code, {
408 babelrc: false,
409 configFile: false,
410 sourceType: 'script',
411 filename: options.filename,
412 });
413 }
414 catch (error) {
415 if (error.message) {
416 // Make the error more readable.
417 // Same errors will contain the full content of the file as the error message
418 // Which makes it hard to find the actual error message.
419 const index = error.message.indexOf(')\n');
420 const msg = index !== -1 ? error.message.substr(0, index + 1) : error.message;
421 throw new Error(`${msg}\nAn error occurred inlining file "${options.filename}"`);
422 }
423 }
424 if (!ast) {
425 throw new Error(`Unknown error occurred inlining file "${options.filename}"`);
426 }
427 if (!USE_LOCALIZE_PLUGINS) {
428 return inlineLocalesDirect(ast, options);
429 }
430 const diagnostics = [];
431 const inputMap = options.map && JSON.parse(options.map);
432 for (const locale of i18n.inlineLocales) {
433 const isSourceLocale = locale === i18n.sourceLocale;
434 // eslint-disable-next-line @typescript-eslint/no-explicit-any
435 const translations = isSourceLocale ? {} : i18n.locales[locale].translation || {};
436 let localeDataContent;
437 if (options.setLocale) {
438 // If locale data is provided, load it and prepend to file
439 const localeDataPath = (_a = i18n.locales[locale]) === null || _a === void 0 ? void 0 : _a.dataPath;
440 if (localeDataPath) {
441 localeDataContent = await loadLocaleData(localeDataPath, true, options.es5);
442 }
443 }
444 const { diagnostics: localeDiagnostics, plugins } = await createI18nPlugins(locale, translations, isSourceLocale ? 'ignore' : options.missingTranslation || 'warning', true, localeDataContent);
445 const transformResult = await core_1.transformFromAstSync(ast, options.code, {
446 filename: options.filename,
447 // using false ensures that babel will NOT search and process sourcemap comments (large memory usage)
448 // The types do not include the false option even though it is valid
449 // eslint-disable-next-line @typescript-eslint/no-explicit-any
450 inputSourceMap: false,
451 babelrc: false,
452 configFile: false,
453 plugins,
454 compact: !environment_options_1.shouldBeautify,
455 sourceMaps: !!inputMap,
456 });
457 diagnostics.push(...localeDiagnostics.messages);
458 if (!transformResult || !transformResult.code) {
459 throw new Error(`Unknown error occurred processing bundle for "${options.filename}".`);
460 }
461 const outputPath = path.join(options.outputPath, i18n.flatOutput ? '' : locale, options.filename);
462 fs.writeFileSync(outputPath, transformResult.code);
463 if (inputMap && transformResult.map) {
464 const outputMap = await mergeSourceMaps(options.code, inputMap, transformResult.code, transformResult.map, options.filename, options.code.length > FAST_SOURCEMAP_THRESHOLD);
465 fs.writeFileSync(outputPath + '.map', JSON.stringify(outputMap));
466 }
467 }
468 return { file: options.filename, diagnostics };
469}
470exports.inlineLocales = inlineLocales;
471async function inlineLocalesDirect(ast, options) {
472 if (!i18n || i18n.inlineLocales.size === 0) {
473 return { file: options.filename, diagnostics: [], count: 0 };
474 }
475 const { default: generate } = await Promise.resolve().then(() => require('@babel/generator'));
476 const utils = await Promise.resolve().then(() => require('@angular/localize/src/tools/src/source_file_utils'));
477 const localizeDiag = await Promise.resolve().then(() => require('@angular/localize/src/tools/src/diagnostics'));
478 const diagnostics = new localizeDiag.Diagnostics();
479 const positions = findLocalizePositions(ast, options, utils);
480 if (positions.length === 0 && !options.setLocale) {
481 return inlineCopyOnly(options);
482 }
483 const inputMap = options.map && JSON.parse(options.map);
484 // Cleanup source root otherwise it will be added to each source entry
485 const mapSourceRoot = inputMap && inputMap.sourceRoot;
486 if (inputMap) {
487 delete inputMap.sourceRoot;
488 }
489 for (const locale of i18n.inlineLocales) {
490 const content = new ReplaceSource(inputMap
491 ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
492 new SourceMapSource(options.code, options.filename, inputMap)
493 : new OriginalSource(options.code, options.filename));
494 const isSourceLocale = locale === i18n.sourceLocale;
495 // eslint-disable-next-line @typescript-eslint/no-explicit-any
496 const translations = isSourceLocale ? {} : i18n.locales[locale].translation || {};
497 for (const position of positions) {
498 const translated = utils.translate(diagnostics, translations, position.messageParts, position.expressions, isSourceLocale ? 'ignore' : options.missingTranslation || 'warning');
499 const expression = utils.buildLocalizeReplacement(translated[0], translated[1]);
500 const { code } = generate(expression);
501 content.replace(position.start, position.end - 1, code);
502 }
503 let outputSource = content;
504 if (options.setLocale) {
505 const setLocaleText = `var $localize=Object.assign(void 0===$localize?{}:$localize,{locale:"${locale}"});\n`;
506 // If locale data is provided, load it and prepend to file
507 let localeDataSource = null;
508 const localeDataPath = i18n.locales[locale] && i18n.locales[locale].dataPath;
509 if (localeDataPath) {
510 const localeDataContent = await loadLocaleData(localeDataPath, true, options.es5);
511 localeDataSource = new OriginalSource(localeDataContent, path.basename(localeDataPath));
512 }
513 outputSource = localeDataSource
514 ? // The semicolon ensures that there is no syntax error between statements
515 new ConcatSource(setLocaleText, localeDataSource, ';\n', content)
516 : new ConcatSource(setLocaleText, content);
517 }
518 const { source: outputCode, map: outputMap } = outputSource.sourceAndMap();
519 const outputPath = path.join(options.outputPath, i18n.flatOutput ? '' : locale, options.filename);
520 fs.writeFileSync(outputPath, outputCode);
521 if (inputMap && outputMap) {
522 outputMap.file = options.filename;
523 if (mapSourceRoot) {
524 outputMap.sourceRoot = mapSourceRoot;
525 }
526 fs.writeFileSync(outputPath + '.map', JSON.stringify(outputMap));
527 }
528 }
529 return { file: options.filename, diagnostics: diagnostics.messages, count: positions.length };
530}
531function inlineCopyOnly(options) {
532 if (!i18n) {
533 throw new Error('i18n options are missing');
534 }
535 for (const locale of i18n.inlineLocales) {
536 const outputPath = path.join(options.outputPath, i18n.flatOutput ? '' : locale, options.filename);
537 fs.writeFileSync(outputPath, options.code);
538 if (options.map) {
539 fs.writeFileSync(outputPath + '.map', options.map);
540 }
541 }
542 return { file: options.filename, diagnostics: [], count: 0 };
543}
544function findLocalizePositions(ast, options, utils) {
545 const positions = [];
546 // Workaround to ensure a path hub is present for traversal
547 const { File } = require('@babel/core');
548 const file = new File({}, { code: options.code, ast });
549 if (options.es5) {
550 core_1.traverse(file.ast, {
551 CallExpression(path) {
552 const callee = path.get('callee');
553 if (callee.isIdentifier() &&
554 callee.node.name === localizeName &&
555 utils.isGlobalIdentifier(callee)) {
556 const [messageParts, expressions] = unwrapLocalizeCall(path, utils);
557 positions.push({
558 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
559 start: path.node.start,
560 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
561 end: path.node.end,
562 messageParts,
563 expressions,
564 });
565 }
566 },
567 });
568 }
569 else {
570 core_1.traverse(file.ast, {
571 TaggedTemplateExpression(path) {
572 if (core_1.types.isIdentifier(path.node.tag) && path.node.tag.name === localizeName) {
573 const [messageParts, expressions] = unwrapTemplateLiteral(path, utils);
574 positions.push({
575 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
576 start: path.node.start,
577 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
578 end: path.node.end,
579 messageParts,
580 expressions,
581 });
582 }
583 },
584 });
585 }
586 return positions;
587}
588function unwrapTemplateLiteral(path, utils) {
589 const [messageParts] = utils.unwrapMessagePartsFromTemplateLiteral(path.get('quasi').get('quasis'));
590 const [expressions] = utils.unwrapExpressionsFromTemplateLiteral(path.get('quasi'));
591 return [messageParts, expressions];
592}
593function unwrapLocalizeCall(path, utils) {
594 const [messageParts] = utils.unwrapMessagePartsFromLocalizeCall(path);
595 const [expressions] = utils.unwrapSubstitutionsFromLocalizeCall(path);
596 return [messageParts, expressions];
597}
598async function loadLocaleData(path, optimize, es5) {
599 // The path is validated during option processing before the build starts
600 const content = fs.readFileSync(path, 'utf8');
601 // Downlevel and optimize the data
602 const transformResult = await core_1.transformAsync(content, {
603 filename: path,
604 // The types do not include the false option even though it is valid
605 // eslint-disable-next-line @typescript-eslint/no-explicit-any
606 inputSourceMap: false,
607 babelrc: false,
608 configFile: false,
609 presets: [
610 [
611 require.resolve('@babel/preset-env'),
612 {
613 bugfixes: true,
614 // IE 11 is the oldest supported browser
615 targets: es5 ? { ie: '11' } : { esmodules: true },
616 },
617 ],
618 ],
619 minified: environment_options_1.allowMinify && optimize,
620 compact: !environment_options_1.shouldBeautify && optimize,
621 comments: !optimize,
622 });
623 if (!transformResult || !transformResult.code) {
624 throw new Error(`Unknown error occurred processing bundle for "${path}".`);
625 }
626 return transformResult.code;
627}