11import path from "path" ;
22
33import { validate } from "schema-utils" ;
4- import pLimit from "p-limit" ;
54import globby from "globby" ;
65import serialize from "serialize-javascript" ;
76import normalizePath from "normalize-path" ;
@@ -11,7 +10,7 @@ import fastGlob from "fast-glob";
1110import { version } from "../package.json" ;
1211
1312import schema from "./options.json" ;
14- import { readFile , stat } from "./utils/promisify " ;
13+ import { readFile , stat , throttleAll } from "./utils" ;
1514
1615const template = / \[ \\ * ( [ \w : ] + ) \\ * \] / i;
1716
@@ -602,7 +601,6 @@ class CopyPlugin {
602601
603602 apply ( compiler ) {
604603 const pluginName = this . constructor . name ;
605- const limit = pLimit ( this . options . concurrency || 100 ) ;
606604
607605 compiler . hooks . thisCompilation . tap ( pluginName , ( compilation ) => {
608606 const logger = compilation . getLogger ( "copy-webpack-plugin" ) ;
@@ -617,138 +615,139 @@ class CopyPlugin {
617615 logger . log ( "starting to add additional assets..." ) ;
618616
619617 const assetMap = new Map ( ) ;
618+ const scheduledTasks = [ ] ;
620619
621- await Promise . all (
622- this . patterns . map ( ( item , index ) =>
623- limit ( async ( ) => {
624- let assets ;
625-
626- try {
627- assets = await CopyPlugin . runPattern (
628- compiler ,
629- compilation ,
630- logger ,
631- cache ,
632- item ,
633- index
634- ) ;
635- } catch ( error ) {
636- compilation . errors . push ( error ) ;
637-
638- return ;
639- }
620+ this . patterns . map ( ( item , index ) =>
621+ scheduledTasks . push ( async ( ) => {
622+ let assets ;
640623
641- if ( assets && assets . length > 0 ) {
642- if ( item . transformAll ) {
643- if ( typeof item . to === "undefined" ) {
644- compilation . errors . push (
645- new Error (
646- `Invalid "pattern.to" for the "pattern.from": "${ item . from } " and "pattern.transformAll" function. The "to" option must be specified.`
647- )
648- ) ;
624+ try {
625+ assets = await CopyPlugin . runPattern (
626+ compiler ,
627+ compilation ,
628+ logger ,
629+ cache ,
630+ item ,
631+ index
632+ ) ;
633+ } catch ( error ) {
634+ compilation . errors . push ( error ) ;
649635
650- return ;
651- }
636+ return ;
637+ }
652638
653- assets . sort ( ( a , b ) =>
654- a . absoluteFilename > b . absoluteFilename
655- ? 1
656- : a . absoluteFilename < b . absoluteFilename
657- ? - 1
658- : 0
639+ if ( assets && assets . length > 0 ) {
640+ if ( item . transformAll ) {
641+ if ( typeof item . to === "undefined" ) {
642+ compilation . errors . push (
643+ new Error (
644+ `Invalid "pattern.to" for the "pattern.from": "${ item . from } " and "pattern.transformAll" function. The "to" option must be specified.`
645+ )
659646 ) ;
660647
661- const mergedEtag =
662- assets . length === 1
663- ? cache . getLazyHashedEtag ( assets [ 0 ] . source . buffer ( ) )
664- : assets . reduce ( ( accumulator , asset , i ) => {
665- // eslint-disable-next-line no-param-reassign
666- accumulator = cache . mergeEtags (
667- i === 1
668- ? cache . getLazyHashedEtag (
669- accumulator . source . buffer ( )
670- )
671- : accumulator ,
672- cache . getLazyHashedEtag ( asset . source . buffer ( ) )
673- ) ;
674-
675- return accumulator ;
676- } ) ;
677-
678- const cacheKeys = `transformAll|${ serialize ( {
679- version,
680- from : item . from ,
681- to : item . to ,
682- transformAll : item . transformAll ,
683- } ) } `;
684- const eTag = cache . getLazyHashedEtag ( mergedEtag ) ;
685- const cacheItem = cache . getItemCache ( cacheKeys , eTag ) ;
686- let transformedAsset = await cacheItem . getPromise ( ) ;
687-
688- if ( ! transformedAsset ) {
689- transformedAsset = { filename : item . to } ;
690-
691- try {
692- transformedAsset . data = await item . transformAll (
693- assets . map ( ( asset ) => {
694- return {
695- data : asset . source . buffer ( ) ,
696- sourceFilename : asset . sourceFilename ,
697- absoluteFilename : asset . absoluteFilename ,
698- } ;
699- } )
700- ) ;
701- } catch ( error ) {
702- compilation . errors . push ( error ) ;
703-
704- return ;
705- }
706-
707- if ( template . test ( item . to ) ) {
708- const contentHash = CopyPlugin . getContentHash (
709- compiler ,
710- compilation ,
711- transformedAsset . data
712- ) ;
713-
714- const { path : interpolatedFilename , info : assetInfo } =
715- compilation . getPathWithInfo ( normalizePath ( item . to ) , {
716- contentHash,
717- chunk : {
718- hash : contentHash ,
719- contentHash,
720- } ,
721- } ) ;
648+ return ;
649+ }
722650
723- transformedAsset . filename = interpolatedFilename ;
724- transformedAsset . info = assetInfo ;
725- }
651+ assets . sort ( ( a , b ) =>
652+ a . absoluteFilename > b . absoluteFilename
653+ ? 1
654+ : a . absoluteFilename < b . absoluteFilename
655+ ? - 1
656+ : 0
657+ ) ;
658+
659+ const mergedEtag =
660+ assets . length === 1
661+ ? cache . getLazyHashedEtag ( assets [ 0 ] . source . buffer ( ) )
662+ : assets . reduce ( ( accumulator , asset , i ) => {
663+ // eslint-disable-next-line no-param-reassign
664+ accumulator = cache . mergeEtags (
665+ i === 1
666+ ? cache . getLazyHashedEtag (
667+ accumulator . source . buffer ( )
668+ )
669+ : accumulator ,
670+ cache . getLazyHashedEtag ( asset . source . buffer ( ) )
671+ ) ;
672+
673+ return accumulator ;
674+ } ) ;
675+
676+ const cacheKeys = `transformAll|${ serialize ( {
677+ version,
678+ from : item . from ,
679+ to : item . to ,
680+ transformAll : item . transformAll ,
681+ } ) } `;
682+ const eTag = cache . getLazyHashedEtag ( mergedEtag ) ;
683+ const cacheItem = cache . getItemCache ( cacheKeys , eTag ) ;
684+ let transformedAsset = await cacheItem . getPromise ( ) ;
685+
686+ if ( ! transformedAsset ) {
687+ transformedAsset = { filename : item . to } ;
688+
689+ try {
690+ transformedAsset . data = await item . transformAll (
691+ assets . map ( ( asset ) => {
692+ return {
693+ data : asset . source . buffer ( ) ,
694+ sourceFilename : asset . sourceFilename ,
695+ absoluteFilename : asset . absoluteFilename ,
696+ } ;
697+ } )
698+ ) ;
699+ } catch ( error ) {
700+ compilation . errors . push ( error ) ;
726701
727- const { RawSource } = compiler . webpack . sources ;
702+ return ;
703+ }
728704
729- transformedAsset . source = new RawSource (
705+ if ( template . test ( item . to ) ) {
706+ const contentHash = CopyPlugin . getContentHash (
707+ compiler ,
708+ compilation ,
730709 transformedAsset . data
731710 ) ;
732- transformedAsset . force = item . force ;
733711
734- await cacheItem . storePromise ( transformedAsset ) ;
712+ const { path : interpolatedFilename , info : assetInfo } =
713+ compilation . getPathWithInfo ( normalizePath ( item . to ) , {
714+ contentHash,
715+ chunk : {
716+ hash : contentHash ,
717+ contentHash,
718+ } ,
719+ } ) ;
720+
721+ transformedAsset . filename = interpolatedFilename ;
722+ transformedAsset . info = assetInfo ;
735723 }
736724
737- assets = [ transformedAsset ] ;
738- }
725+ const { RawSource } = compiler . webpack . sources ;
739726
740- const priority = item . priority || 0 ;
727+ transformedAsset . source = new RawSource (
728+ transformedAsset . data
729+ ) ;
730+ transformedAsset . force = item . force ;
741731
742- if ( ! assetMap . has ( priority ) ) {
743- assetMap . set ( priority , [ ] ) ;
732+ await cacheItem . storePromise ( transformedAsset ) ;
744733 }
745734
746- assetMap . get ( priority ) . push ( ...assets ) ;
735+ assets = [ transformedAsset ] ;
736+ }
737+
738+ const priority = item . priority || 0 ;
739+
740+ if ( ! assetMap . has ( priority ) ) {
741+ assetMap . set ( priority , [ ] ) ;
747742 }
748- } )
749- )
743+
744+ assetMap . get ( priority ) . push ( ...assets ) ;
745+ }
746+ } )
750747 ) ;
751748
749+ await throttleAll ( this . options . concurrency || 100 , scheduledTasks ) ;
750+
752751 const assets = [ ...assetMap . entries ( ) ] . sort ( ( a , b ) => a [ 0 ] - b [ 0 ] ) ;
753752
754753 // Avoid writing assets inside `p-limit`, because it creates concurrency.
0 commit comments