@@ -75,6 +75,10 @@ test("should output files to cache directory when cache type is filesystem", asy
7575 presets : [ "@babel/preset-env" ] ,
7676 } ,
7777 } ,
78+ // when cache.type is filesystem, webpack will try to cache the loader result if they
79+ // are cacheable (by default). The webpack cache will then be hit before the babel-loader
80+ // cache. To test the babel-loader cache behaviour, we have to mark the loader results
81+ // as uncacheable
7882 {
7983 loader : "./test/fixtures/uncacheable-passthrough-loader.cjs" ,
8084 } ,
@@ -595,3 +599,104 @@ test("should work with memory type webpack cache", async () => {
595599 } ) ;
596600 } ) ;
597601} ) ;
602+
603+ test ( "it should work with custom webpack cache plugin" , async ( ) => {
604+ class CustomCachePlugin {
605+ /**
606+ * Apply the plugin
607+ * @param {import("webpack").Compiler } compiler the compiler instance
608+ */
609+ apply ( compiler ) {
610+ let cache = Object . create ( null ) ;
611+ const pluginName = this . constructor . name ;
612+
613+ compiler . cache . hooks . store . tap ( pluginName , ( identifier , etag , data ) => {
614+ cache [ identifier ] = { etag, data } ;
615+ } ) ;
616+
617+ compiler . cache . hooks . get . tap (
618+ pluginName ,
619+ ( identifier , etag , gotHandlers ) => {
620+ if ( ! ( identifier in cache ) ) {
621+ return null ;
622+ } else if ( cache [ identifier ] != null ) {
623+ const cacheEntry = cache [ identifier ] ;
624+ if ( cacheEntry . etag === etag ) {
625+ return cacheEntry . data ;
626+ } else {
627+ return null ;
628+ }
629+ }
630+ gotHandlers . push ( ( result , callback ) => {
631+ if ( result === undefined ) {
632+ cache [ identifier ] = null ;
633+ } else {
634+ cache [ identifier ] = { etag, data : result } ;
635+ }
636+ return callback ( ) ;
637+ } ) ;
638+ } ,
639+ ) ;
640+
641+ compiler . cache . hooks . shutdown . tap (
642+ pluginName ,
643+ ( ) => ( cache = Object . create ( null ) ) ,
644+ ) ;
645+ }
646+ }
647+
648+ const config = Object . assign ( { } , globalConfig , {
649+ // disable builtin webpack cache so that CustomCachePlugin can provide the cache backend
650+ cache : false ,
651+ entry : path . join ( __dirname , "fixtures/constant.js" ) ,
652+ output : {
653+ path : context . directory ,
654+ } ,
655+ module : {
656+ rules : [
657+ {
658+ test : / \. j s x ? / ,
659+ exclude : / n o d e _ m o d u l e s / ,
660+ use : [
661+ {
662+ loader : babelLoader ,
663+ options : {
664+ cacheDirectory : true ,
665+ configFile : false ,
666+ presets : [ "@babel/preset-env" ] ,
667+ } ,
668+ } ,
669+ {
670+ loader : "./test/fixtures/uncacheable-passthrough-loader.cjs" ,
671+ } ,
672+ ] ,
673+ } ,
674+ ] ,
675+ } ,
676+ plugins : [ new CustomCachePlugin ( ) ] ,
677+ stats : {
678+ loggingDebug : [ "babel-loader" , CustomCachePlugin . name ] ,
679+ } ,
680+ } ) ;
681+
682+ return new Promise ( ( resolve , reject ) => {
683+ const compiler = webpack ( config ) ;
684+ compiler . run ( ( err , stats ) => {
685+ if ( err ) reject ( err ) ;
686+ assert . match (
687+ stats . toString ( config . stats ) ,
688+ / n o r m a l i z i n g l o a d e r o p t i o n s \n \s + r e s o l v i n g B a b e l c o n f i g s \n \s + c a c h e i s e n a b l e d \n \s + g e t t i n g c a c h e f o r .+ \n \s + m i s s e d c a c h e f o r .+ \n \s + a p p l y i n g B a b e l t r a n s f o r m \n \s + c a c h i n g r e s u l t f o r .+ \n \s + c a c h e d r e s u l t f o r .+ / ,
689+ "The first run stat does not match the snapshot regex" ,
690+ ) ;
691+ compiler . run ( ( err , newStats ) => {
692+ if ( err ) reject ( err ) ;
693+ assert . match (
694+ newStats . toString ( config . stats ) ,
695+ / n o r m a l i z i n g l o a d e r o p t i o n s \n \s + r e s o l v i n g B a b e l c o n f i g s \n \s + c a c h e i s e n a b l e d \n \s + g e t t i n g c a c h e f o r .+ \n \s + f o u n d c a c h e f o r .+ / ,
696+ "The second run stat does not match the snapshot regex" ,
697+ ) ;
698+ resolve ( ) ;
699+ } ) ;
700+ } ) ;
701+ } ) ;
702+ } ) ;
0 commit comments