Skip to content

Commit 6a2b119

Browse files
committed
perf(@angular-devkit/build-angular): cache JavaScriptOptimizerPlugin results
With this change we cache JavaScriptOptimizerPlugin results in memory or on the file system based on the caching strategy used.
1 parent 41e6457 commit 6a2b119

File tree

1 file changed

+43
-17
lines changed

1 file changed

+43
-17
lines changed

packages/angular_devkit/build_angular/src/webpack/plugins/javascript-optimizer-plugin.ts

+43-17
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import Piscina from 'piscina';
1010
import { ScriptTarget } from 'typescript';
11+
import type { Compiler, sources } from 'webpack';
1112
import { maxWorkers } from '../../utils/environment-options';
1213

1314
/**
@@ -74,7 +75,7 @@ export interface JavaScriptOptimizerOptions {
7475
export class JavaScriptOptimizerPlugin {
7576
constructor(public options: Partial<JavaScriptOptimizerOptions> = {}) {}
7677

77-
apply(compiler: import('webpack').Compiler) {
78+
apply(compiler: Compiler) {
7879
const { OriginalSource, SourceMapSource } = compiler.webpack.sources;
7980

8081
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
@@ -85,19 +86,43 @@ export class JavaScriptOptimizerPlugin {
8586
},
8687
async (compilationAssets) => {
8788
const scriptsToOptimize = [];
89+
const cache =
90+
compilation.options.cache && compilation.getCache('JavaScriptOptimizerPlugin');
8891

8992
// Analyze the compilation assets for scripts that require optimization
9093
for (const assetName of Object.keys(compilationAssets)) {
91-
if (assetName.endsWith('.js')) {
92-
const scriptAsset = compilation.getAsset(assetName);
93-
if (scriptAsset && !scriptAsset.info.minimized) {
94-
const { source, map } = scriptAsset.source.sourceAndMap();
95-
scriptsToOptimize.push({
96-
name: scriptAsset.name,
97-
code: typeof source === 'string' ? source : source.toString(),
98-
map,
99-
});
94+
if (!assetName.endsWith('.js')) {
95+
continue;
96+
}
97+
98+
const scriptAsset = compilation.getAsset(assetName);
99+
100+
if (scriptAsset && !scriptAsset.info.minimized) {
101+
const { source: scriptAssetSource, name } = scriptAsset;
102+
let cacheItem;
103+
104+
if (cache) {
105+
const eTag = cache.getLazyHashedEtag(scriptAssetSource);
106+
cacheItem = cache.getItemCache(name, eTag);
107+
const cachedOutput = await cacheItem.getPromise<
108+
{ source: sources.Source } | undefined
109+
>();
110+
111+
if (cachedOutput) {
112+
compilation.updateAsset(name, cachedOutput.source, {
113+
minimized: true,
114+
});
115+
continue;
116+
}
100117
}
118+
119+
const { source, map } = scriptAssetSource.sourceAndMap();
120+
scriptsToOptimize.push({
121+
name: scriptAsset.name,
122+
code: typeof source === 'string' ? source : source.toString(),
123+
map,
124+
cacheItem,
125+
});
101126
}
102127
}
103128

@@ -154,7 +179,7 @@ export class JavaScriptOptimizerPlugin {
154179
// Enqueue script optimization tasks and update compilation assets as the tasks complete
155180
try {
156181
const tasks = [];
157-
for (const { name, code, map } of scriptsToOptimize) {
182+
for (const { name, code, map, cacheItem } of scriptsToOptimize) {
158183
tasks.push(
159184
workerPool
160185
.run({
@@ -167,13 +192,14 @@ export class JavaScriptOptimizerPlugin {
167192
})
168193
.then(
169194
({ code, name, map }) => {
170-
let optimizedAsset;
171-
if (map) {
172-
optimizedAsset = new SourceMapSource(code, name, map);
173-
} else {
174-
optimizedAsset = new OriginalSource(code, name);
175-
}
195+
const optimizedAsset = map
196+
? new SourceMapSource(code, name, map)
197+
: new OriginalSource(code, name);
176198
compilation.updateAsset(name, optimizedAsset, { minimized: true });
199+
200+
return cacheItem?.storePromise({
201+
source: optimizedAsset,
202+
});
177203
},
178204
(error) => {
179205
const optimizationError = new compiler.webpack.WebpackError(

0 commit comments

Comments
 (0)