11import { writeFileSync } from 'fs' ;
22import { extname , relative } from 'path' ;
33
4- import { Compiler , Plugin , compilation , Configuration , Stats } from 'webpack' ;
4+ import { Compiler , Compilation , sources , StatsModule , StatsCompilation } from 'webpack' ;
55
66import { ChunkMap , Chunks , ImportedStat , Asset } from './types' ;
77
88const merge = require ( 'lodash/merge' ) ;
99
1010type WebStats = Required <
11- Pick < Stats . ToJsonOutput , 'chunks' | 'assets' | 'namedChunkGroups' | 'publicPath' | 'outputPath' >
11+ Pick < StatsCompilation , 'chunks' | 'assets' | 'namedChunkGroups' | 'publicPath' | 'outputPath' >
1212> ;
1313
1414const moduleToChunks = ( { chunks } : WebStats ) => {
1515 const manifest : Record < string , number | string > = { } ;
1616 chunks . forEach ( ( { id, modules } ) => {
1717 if ( modules ) {
18- modules . forEach ( ( module : Stats . FnModules ) => {
19- manifest [ module . id ] = id ;
18+ modules . forEach ( ( module : StatsModule ) => {
19+ if ( module . id && id ) manifest [ module . id ] = id ;
2020 } ) ;
2121 }
2222 } ) ;
@@ -39,7 +39,7 @@ const extractPrefetch = (prefetch: any[] = []): number[] =>
3939
4040const mapChunkNumbers = ( { assets } : WebStats ) : ChunkMap =>
4141 assets . reduce ( ( acc , { name, chunks } ) => {
42- chunks . forEach ( ( chunk ) => {
42+ chunks ? .forEach ( ( chunk ) => {
4343 acc [ chunk ] = acc [ chunk ] || { } ;
4444 const type = getAssetType ( name ) ;
4545 acc [ chunk ] [ type ] = acc [ chunk ] [ type ] || [ ] ;
@@ -53,23 +53,23 @@ const getAssets = ({ assets }: WebStats): Asset[] =>
5353 assets ! . map ( ( { name, size } ) => ( { name, size, type : getAssetType ( name ) } ) ) ;
5454
5555const getChunks = ( { namedChunkGroups } : WebStats ) : Chunks =>
56- Object . keys ( namedChunkGroups ! ) . reduce ( ( acc , key ) => {
56+ Object . keys ( namedChunkGroups ) . reduce ( ( acc , key ) => {
5757 const { chunks, children } = namedChunkGroups [ key ] ;
5858 acc [ key ] = {
59- load : chunks ,
60- preload : children . preload ? extractPrefetch ( children . preload as any ) : [ ] ,
61- prefetch : children . prefetch ? extractPrefetch ( children . prefetch as any ) : [ ] ,
59+ load : chunks || [ ] ,
60+ preload : children ? .preload ? extractPrefetch ( children . preload ) : [ ] ,
61+ prefetch : children ? .prefetch ? extractPrefetch ( children . prefetch ) : [ ] ,
6262 } ;
6363
6464 return acc ;
6565 } , { } as Chunks ) ;
66-
66+
6767const resolveAliases = ( cwd : string , aliases : Record < string , string | string [ ] > ) : Record < string , string | string [ ] > => {
6868 return Object . keys ( aliases ) . reduce ( ( acc , key ) => {
6969 const alias = aliases [ key ] ;
70- const paths = Array . isArray ( alias ) ? alias . map ( aliasPath => relative ( cwd , aliasPath ) ) : relative ( cwd , alias ) ;
71- return { ...acc , [ key ] : paths }
72- } , { } )
70+ const paths = Array . isArray ( alias ) ? alias . map ( ( aliasPath ) => relative ( cwd , aliasPath ) ) : relative ( cwd , alias ) ;
71+ return { ...acc , [ key ] : paths } ;
72+ } , { } ) ;
7373} ;
7474
7575export const importStats = ( stats : WebStats , extraProps : Record < string , any > = { } ) : ImportedStat => {
@@ -101,10 +101,10 @@ interface Options {
101101/**
102102 * Webpack plugin
103103 */
104- export class ImportedPlugin implements Plugin {
104+ export class ImportedPlugin {
105105 constructor ( private output : string , private options : Options = { } , private cache = { } ) { }
106106
107- emitCallback = ( compilation : compilation . Compilation , done : ( ) => void ) => {
107+ handleEmit = ( compilation : Compilation ) => {
108108 const stats = compilation . getStats ( ) . toJson ( {
109109 hash : true ,
110110 publicPath : true ,
@@ -119,7 +119,7 @@ export class ImportedPlugin implements Plugin {
119119 const cwd = process . cwd ( ) ;
120120 // not quite yet
121121 // const modules = compilation.options.resolve.modules;
122- const aliases = resolveAliases ( cwd , ( ( compilation as any ) . options as Configuration ) . resolve ! . alias || { } ) ;
122+ const aliases = resolveAliases ( cwd , ( compilation as any ) . options . resolve ! . alias || { } ) ;
123123 // const {publicPath, outputPath} = stats;
124124
125125 const result : ImportedStat = importStats ( stats , { aliases } ) ;
@@ -130,25 +130,49 @@ export class ImportedPlugin implements Plugin {
130130
131131 const stringResult = JSON . stringify ( result , null , 2 ) ;
132132
133+ if ( this . options . saveToFile ) {
134+ writeFileSync ( this . options . saveToFile , stringResult ) ;
135+ }
136+
133137 if ( this . output ) {
134- compilation . assets [ this . output ] = {
135- size ( ) {
136- return stringResult . length ;
137- } ,
138+ return {
138139 source ( ) {
139140 return stringResult ;
140141 } ,
142+ size ( ) {
143+ return stringResult . length ;
144+ } ,
141145 } ;
142146 }
143147
144- if ( this . options . saveToFile ) {
145- writeFileSync ( this . options . saveToFile , stringResult ) ;
146- }
147-
148- done ( ) ;
148+ return null ;
149149 } ;
150150
151151 apply ( compiler : Compiler ) {
152- compiler . hooks . emit . tapAsync ( 'ImportedPlugin' , this . emitCallback ) ;
152+ const version = 'jsonpFunction' in compiler . options . output ? 4 : 5 ;
153+
154+ if ( version === 4 ) {
155+ compiler . hooks . emit . tap ( 'ImportedPlugin' , ( compilation ) => {
156+ const asset = this . handleEmit ( compilation ) ;
157+ if ( asset ) {
158+ compilation . assets [ this . output ] = asset as sources . Source ;
159+ }
160+ } ) ;
161+ } else {
162+ compiler . hooks . make . tap ( 'ImportedPlugin' , ( compilation ) => {
163+ compilation . hooks . processAssets . tap (
164+ {
165+ name : 'ImportedPlugin' ,
166+ stage : compiler . webpack . Compilation . PROCESS_ASSETS_STAGE_REPORT ,
167+ } ,
168+ ( ) => {
169+ const asset = this . handleEmit ( compilation ) ;
170+ if ( asset ) {
171+ compilation . emitAsset ( this . output , asset as sources . Source ) ;
172+ }
173+ }
174+ ) ;
175+ } ) ;
176+ }
153177 }
154178}
0 commit comments