source: trip-planner-front/node_modules/@angular-devkit/build-angular/src/webpack/plugins/javascript-optimizer-plugin.js@ 6a3a178

Last change on this file since 6a3a178 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 7.5 KB
Line 
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 */
9var __importDefault = (this && this.__importDefault) || function (mod) {
10 return (mod && mod.__esModule) ? mod : { "default": mod };
11};
12Object.defineProperty(exports, "__esModule", { value: true });
13exports.JavaScriptOptimizerPlugin = void 0;
14const piscina_1 = __importDefault(require("piscina"));
15const typescript_1 = require("typescript");
16const environment_options_1 = require("../../utils/environment-options");
17const esbuild_executor_1 = require("./esbuild-executor");
18/**
19 * The maximum number of Workers that will be created to execute optimize tasks.
20 */
21const MAX_OPTIMIZE_WORKERS = environment_options_1.maxWorkers;
22/**
23 * The name of the plugin provided to Webpack when tapping Webpack compiler hooks.
24 */
25const PLUGIN_NAME = 'angular-javascript-optimizer';
26/**
27 * A Webpack plugin that provides JavaScript optimization capabilities.
28 *
29 * The plugin uses both `esbuild` and `terser` to provide both fast and highly-optimized
30 * code output. `esbuild` is used as an initial pass to remove the majority of unused code
31 * as well as shorten identifiers. `terser` is then used as a secondary pass to apply
32 * optimizations not yet implemented by `esbuild`.
33 */
34class JavaScriptOptimizerPlugin {
35 constructor(options = {}) {
36 this.options = options;
37 }
38 apply(compiler) {
39 const { OriginalSource, SourceMapSource } = compiler.webpack.sources;
40 compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
41 compilation.hooks.processAssets.tapPromise({
42 name: PLUGIN_NAME,
43 stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE,
44 }, async (compilationAssets) => {
45 const scriptsToOptimize = [];
46 const cache = compilation.options.cache && compilation.getCache('JavaScriptOptimizerPlugin');
47 // Analyze the compilation assets for scripts that require optimization
48 for (const assetName of Object.keys(compilationAssets)) {
49 if (!assetName.endsWith('.js')) {
50 continue;
51 }
52 const scriptAsset = compilation.getAsset(assetName);
53 // Skip assets that have already been optimized or are verbatim copies (project assets)
54 if (!scriptAsset || scriptAsset.info.minimized || scriptAsset.info.copied) {
55 continue;
56 }
57 const { source: scriptAssetSource, name } = scriptAsset;
58 let cacheItem;
59 if (cache) {
60 const eTag = cache.getLazyHashedEtag(scriptAssetSource);
61 cacheItem = cache.getItemCache(name, eTag);
62 const cachedOutput = await cacheItem.getPromise();
63 if (cachedOutput) {
64 compilation.updateAsset(name, cachedOutput.source, {
65 minimized: true,
66 });
67 continue;
68 }
69 }
70 const { source, map } = scriptAssetSource.sourceAndMap();
71 scriptsToOptimize.push({
72 name: scriptAsset.name,
73 code: typeof source === 'string' ? source : source.toString(),
74 map,
75 cacheItem,
76 });
77 }
78 if (scriptsToOptimize.length === 0) {
79 return;
80 }
81 // Ensure all replacement values are strings which is the expected type for esbuild
82 let define;
83 if (this.options.define) {
84 define = {};
85 for (const [key, value] of Object.entries(this.options.define)) {
86 define[key] = String(value);
87 }
88 }
89 let target = 2017;
90 if (this.options.target) {
91 if (this.options.target <= typescript_1.ScriptTarget.ES5) {
92 target = 5;
93 }
94 else if (this.options.target < typescript_1.ScriptTarget.ESNext) {
95 target = Number(typescript_1.ScriptTarget[this.options.target].slice(2));
96 }
97 else {
98 target = 2020;
99 }
100 }
101 // Setup the options used by all worker tasks
102 const optimizeOptions = {
103 sourcemap: this.options.sourcemap,
104 define,
105 keepNames: this.options.keepNames,
106 target,
107 removeLicenses: this.options.removeLicenses,
108 advanced: this.options.advanced,
109 // Perform a single native esbuild support check.
110 // This removes the need for each worker to perform the check which would
111 // otherwise require spawning a separate process per worker.
112 alwaysUseWasm: !esbuild_executor_1.EsbuildExecutor.hasNativeSupport(),
113 };
114 // Sort scripts so larger scripts start first - worker pool uses a FIFO queue
115 scriptsToOptimize.sort((a, b) => a.code.length - b.code.length);
116 // Initialize the task worker pool
117 const workerPath = require.resolve('./javascript-optimizer-worker');
118 const workerPool = new piscina_1.default({
119 filename: workerPath,
120 maxThreads: MAX_OPTIMIZE_WORKERS,
121 });
122 // Enqueue script optimization tasks and update compilation assets as the tasks complete
123 try {
124 const tasks = [];
125 for (const { name, code, map, cacheItem } of scriptsToOptimize) {
126 tasks.push(workerPool
127 .run({
128 asset: {
129 name,
130 code,
131 map,
132 },
133 options: optimizeOptions,
134 })
135 .then(({ code, name, map }) => {
136 const optimizedAsset = map
137 ? new SourceMapSource(code, name, map)
138 : new OriginalSource(code, name);
139 compilation.updateAsset(name, optimizedAsset, { minimized: true });
140 return cacheItem === null || cacheItem === void 0 ? void 0 : cacheItem.storePromise({
141 source: optimizedAsset,
142 });
143 }, (error) => {
144 const optimizationError = new compiler.webpack.WebpackError(`Optimization error [${name}]: ${error.stack || error.message}`);
145 compilation.errors.push(optimizationError);
146 }));
147 }
148 await Promise.all(tasks);
149 }
150 finally {
151 void workerPool.destroy();
152 }
153 });
154 });
155 }
156}
157exports.JavaScriptOptimizerPlugin = JavaScriptOptimizerPlugin;
Note: See TracBrowser for help on using the repository browser.