8
8
9
9
import Piscina from 'piscina' ;
10
10
import { ScriptTarget } from 'typescript' ;
11
+ import type { Compiler , sources } from 'webpack' ;
11
12
import { maxWorkers } from '../../utils/environment-options' ;
12
13
13
14
/**
@@ -74,7 +75,7 @@ export interface JavaScriptOptimizerOptions {
74
75
export class JavaScriptOptimizerPlugin {
75
76
constructor ( public options : Partial < JavaScriptOptimizerOptions > = { } ) { }
76
77
77
- apply ( compiler : import ( 'webpack' ) . Compiler ) {
78
+ apply ( compiler : Compiler ) {
78
79
const { OriginalSource, SourceMapSource } = compiler . webpack . sources ;
79
80
80
81
compiler . hooks . compilation . tap ( PLUGIN_NAME , ( compilation ) => {
@@ -85,19 +86,43 @@ export class JavaScriptOptimizerPlugin {
85
86
} ,
86
87
async ( compilationAssets ) => {
87
88
const scriptsToOptimize = [ ] ;
89
+ const cache =
90
+ compilation . options . cache && compilation . getCache ( 'JavaScriptOptimizerPlugin' ) ;
88
91
89
92
// Analyze the compilation assets for scripts that require optimization
90
93
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
+ }
100
117
}
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
+ } ) ;
101
126
}
102
127
}
103
128
@@ -154,7 +179,7 @@ export class JavaScriptOptimizerPlugin {
154
179
// Enqueue script optimization tasks and update compilation assets as the tasks complete
155
180
try {
156
181
const tasks = [ ] ;
157
- for ( const { name, code, map } of scriptsToOptimize ) {
182
+ for ( const { name, code, map, cacheItem } of scriptsToOptimize ) {
158
183
tasks . push (
159
184
workerPool
160
185
. run ( {
@@ -167,13 +192,14 @@ export class JavaScriptOptimizerPlugin {
167
192
} )
168
193
. then (
169
194
( { 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 ) ;
176
198
compilation . updateAsset ( name , optimizedAsset , { minimized : true } ) ;
199
+
200
+ return cacheItem ?. storePromise ( {
201
+ source : optimizedAsset ,
202
+ } ) ;
177
203
} ,
178
204
( error ) => {
179
205
const optimizationError = new compiler . webpack . WebpackError (
0 commit comments