文章目录 
 作用 涉及 webpack API 获取chunkGraph 获取当前编译过程中被使用过的 module id:compilation.usedModuleIds 获取当前编译过程中所有的模块对象:compilation.modules 判断 module 是否需要生成 id:module.needId 获取指定module 的 module id:chunkGraph.getModuleId 获取 module 属于多少个chunk:chunkGraph.getNumberOfModuleChunks 获取 module 标识符:module.identifier 设置 module id:chunkGraph.setModuleId  
  实现 constructor apply getUsedModuleIdsAndModules  
  
 
 
 作用  
将模块打包生成后的 id 变成 hash 值,用于生成稳定的模块 id   
new  webpack. ids. HashedModuleIdsPlugin ( ) , 
  
 
 涉及 webpack API  
 
const  chunkGraph =  compilation. chunkGraph; 
  
  获取当前编译过程中被使用过的 module id:compilation.usedModuleIds     
compilation. usedModuleIds;   
  
  获取当前编译过程中所有的模块对象:compilation.modules  
      
for  ( const  module of  compilation. modules)  { 
	
} 
  
  判断 module 是否需要生成 id:module.needId  
  表示该模块是否需要一个模块 id, 在 webpack 的编译过程中,有些模块可能不需要一个独立的模块 id,例如一些内置模块或者一些被动态加载的模块      
for  ( const  module of  compilation. modules)  { 
	if  ( ! module. needId)  continue ; 
	const  moduleId =  chunkGraph. getModuleId ( module) ; 
} 
  
  获取指定module 的 module id:chunkGraph.getModuleId     
for  ( const  module of  compilation. modules)  { 
	if  ( ! module. needId)  continue ; 
	const  moduleId =  chunkGraph. getModuleId ( module) ; 
} 
  
  获取 module 属于多少个chunk:chunkGraph.getNumberOfModuleChunks     
if  ( chunkGraph. getNumberOfModuleChunks ( module)  !==  0 ) { 
 
} 
  
  获取 module 标识符:module.identifier  
  根据 module 的 type、request、layer创建      
for  ( const  module of  compilation. modules)  { 
	module. identifier ( ) 
} 
identifier ( )  { 
	if  ( this . layer ===  null )  { 
		if  ( this . type ===  "javascript/auto" )  { 
			return  this . request;  
		}  else  { 
			return  ` ${ this . type} | ${ this . request} ` ; 
		} 
	}  else  { 
		return  ` ${ this . type} | ${ this . request} | ${ this . layer} ` ; 
	} 
} 
  
  设置 module id:chunkGraph.setModuleId     
for  ( const  module of  compilation. modules)  { 
	const  moduleId=  'xxx' 
	chunkGraph. setModuleId ( module,  moduleId) ; 
} 
  
 实现  
 constructor  
class  HashedModuleIdsPlugin  { 
	
	constructor ( options =  { }  )  { 
		validate ( options) ; 
		
		this . options =  { 
			context :  null , 
			hashFunction :  "md4" , 
			hashDigest :  "base64" , 
			hashDigestLength :  4 , 
			... options
		} ; 
	} 
} 
  
 apply  
apply ( compiler )  { 
	const  options =  this . options; 
	compiler. hooks. compilation. tap ( "HashedModuleIdsPlugin" ,  compilation  =>  { 
		
		compilation. hooks. moduleIds. tap ( "HashedModuleIdsPlugin" ,  ( )  =>  { 
			const  chunkGraph =  compilation. chunkGraph; 
			const  context =  this . options. context 
				?  this . options. context
				:  compiler. context; 
			
			const  [ usedIds,  modules]  =  getUsedModuleIdsAndModules ( compilation) ; 
			
			const  modulesInNaturalOrder =  modules. sort ( 
				compareModulesByPreOrderIndexOrIdentifier ( compilation. moduleGraph) 
			) ; 
			for  ( const  module of  modulesInNaturalOrder)  { 
				
				const  ident =  getFullModuleName ( module,  context,  compiler. root) ;  
				
				const  hash =  createHash ( options. hashFunction) ; 
				hash. update ( ident ||  "" ) ; 
				const  hashId =   ( 
					hash. digest ( options. hashDigest) 
				) ; 
				
				let  len =  options. hashDigestLength; 
				
				while  ( usedIds. has ( hashId. slice ( 0 ,  len) ) )  len++ ; 
				const  moduleId =  hashId. slice ( 0 ,  len) ; 
				
				chunkGraph. setModuleId ( module,  moduleId) ; 
				
				usedIds. add ( moduleId) ; 
			} 
		} ) ; 
	} ) ; 
} 
  
 getUsedModuleIdsAndModules  
获取所有效的 modules 和已经编译使用过的 module id 只有需要生成 module id 的 module 且之前没有创建过且 module 在某个 chunk 中才有效   
const  getUsedModuleIdsAndModules  =  ( compilation,  filter )  =>  { 
	const  chunkGraph =  compilation. chunkGraph; 
	const  modules =  [ ] ; 
	const  usedIds =  new  Set ( ) ; 
	
	if  ( compilation. usedModuleIds)  { 
		for  ( const  id of  compilation. usedModuleIds)  { 
			usedIds. add ( id +  "" ) ; 
		} 
	} 
	
	for  ( const  module of  compilation. modules)  { 
		
		if  ( ! module. needId)  continue ; 
		
		const  moduleId =  chunkGraph. getModuleId ( module) ; 
		
		if  ( moduleId !==  null )  { 
			
			usedIds. add ( moduleId +  "" ) ; 
		}  else  { 
			
			if  ( 
				( ! filter ||  filter ( module) )  && 
				chunkGraph. getNumberOfModuleChunks ( module)  !==  0 
			)  { 
				
				modules. push ( module) ; 
			} 
		} 
	} 
	return  [ usedIds,  modules] ; 
} ;