import type { WebpackPluginInstance , Compiler , NormalModule } from 'webpack' ; interface LoaderConfig { loader : string ; options ? : Record < string , any > ; } interface Options { loaderConfig ? : Record < string , LoaderConfig > ; } class WebpackPluginQueryLoader implements WebpackPluginInstance { private options : Options ; private pluginName : string ; private resourceMap : Map < string , boolean > ; constructor ( options ) { const defaultLoaderConfig = { raw : { loader : require . resolve ( '@builder/pack/deps/raw-loader' ) , } , url : { loader : require . resolve ( '@builder/pack/deps/url-loader' ) , } , worker : { loader : require . resolve ( '@builder/pack/deps/worker-loader' ) , } , sharedworker : { loader : require . resolve ( '@builder/pack/deps/worker-loader' ) , options : { worker : 'SharedWorker' , } , } , 'worker&inline' : { loader : require . resolve ( '@builder/pack/deps/worker-loader' ) , options : { inline : 'fallback' , } , } , } ; this . options = Object . assign ( options || { } , defaultLoaderConfig ) ; this . pluginName = 'WebpackPluginQueryLoader' ; this . resourceMap = new Map ( ) ; } private getMatchedQuery ( query ) { const supportedQuery = Object . keys ( this . options ) ; const regexpForMatchRequest = new RegExp ( `^\\?(${ supportedQuery . join ( '|' ) })$` ) ; const [ , matchedQuery ] = query . match ( regexpForMatchRequest ) || [ ] ; return matchedQuery ; } public apply ( compiler ) { compiler . hooks . normalModuleFactory . tap ( this . pluginName , ( normalModuleFactory ) => { normalModuleFactory . hooks . afterResolve . tap ( this . pluginName , ( resolveData ) => { const moduleData = resolveData . createData as NormalModule ; const matchedQuery = moduleData ?. resourceResolveData ?. query && this . getMatchedQuery ( moduleData ?. resourceResolveData ?. query ) ; if ( matchedQuery && ! this . resourceMap . get ( moduleData . resource ) ) { const loaderConfig = this . options [ matchedQuery ] as LoaderConfig ; moduleData . loaders . push ( { ident : null , type : null , options : null , ... loaderConfig } ) ; this . resourceMap . set ( moduleData . resource , true ) ; } } ) ; } ) ; compiler . hooks . emit . tap ( this . pluginName , ( ) => { this . resourceMap = new Map ( ) ; } ) ; } } export default WebpackPluginQueryLoader ;