2020-02-20 03:25:49 +08:00
/ *
MIT License http : //www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @ sokra
* /
"use strict" ;
const RuntimeGlobals = require ( "../RuntimeGlobals" ) ;
const JavascriptModulesPlugin = require ( "../javascript/JavascriptModulesPlugin" ) ;
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
/** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
/** @typedef {import("../util/Hash")} Hash */
2021-02-05 06:11:11 +08:00
const COMMON _LIBRARY _NAME _MESSAGE =
"Common configuration options that specific library names are 'output.library[.name]', 'entry.xyz.library[.name]', 'ModuleFederationPlugin.name' and 'ModuleFederationPlugin.library[.name]'." ;
2020-02-20 03:25:49 +08:00
/ * *
* @ template T
* @ typedef { Object } LibraryContext
* @ property { Compilation } compilation
* @ property { T } options
* /
/ * *
* @ template T
* /
class AbstractLibraryPlugin {
/ * *
* @ param { Object } options options
* @ param { string } options . pluginName name of the plugin
* @ param { LibraryType } options . type used library type
* /
constructor ( { pluginName , type } ) {
this . _pluginName = pluginName ;
this . _type = type ;
this . _parseCache = new WeakMap ( ) ;
}
/ * *
2020-04-23 16:48:36 +08:00
* Apply the plugin
2020-02-20 03:25:49 +08:00
* @ param { Compiler } compiler the compiler instance
* @ returns { void }
* /
apply ( compiler ) {
const { _pluginName } = this ;
compiler . hooks . thisCompilation . tap ( _pluginName , compilation => {
compilation . hooks . finishModules . tap ( _pluginName , ( ) => {
2020-07-28 00:09:48 +08:00
for ( const [
name ,
{
dependencies : deps ,
options : { library }
}
] of compilation . entries ) {
2020-02-26 19:34:57 +08:00
const options = this . _parseOptionsCached (
library !== undefined ? library : compilation . outputOptions . library
) ;
if ( options !== false ) {
2020-02-20 03:25:49 +08:00
const dep = deps [ deps . length - 1 ] ;
if ( dep ) {
const module = compilation . moduleGraph . getModule ( dep ) ;
if ( module ) {
2020-07-28 00:09:48 +08:00
this . finishEntryModule ( module , name , { options , compilation } ) ;
2020-02-20 03:25:49 +08:00
}
}
}
}
} ) ;
2020-02-26 19:34:57 +08:00
const getOptionsForChunk = chunk => {
if ( compilation . chunkGraph . getNumberOfEntryModules ( chunk ) === 0 )
return false ;
2020-09-08 00:02:14 +08:00
const options = chunk . getEntryOptions ( ) ;
const library = options && options . library ;
2020-02-26 19:34:57 +08:00
return this . _parseOptionsCached (
library !== undefined ? library : compilation . outputOptions . library
) ;
} ;
2020-02-20 03:25:49 +08:00
compilation . hooks . additionalChunkRuntimeRequirements . tap (
_pluginName ,
( chunk , set ) => {
2020-02-26 19:34:57 +08:00
const options = getOptionsForChunk ( chunk ) ;
2020-02-20 03:25:49 +08:00
if ( options !== false ) {
this . runtimeRequirements ( chunk , set , { options , compilation } ) ;
}
}
) ;
const hooks = JavascriptModulesPlugin . getCompilationHooks ( compilation ) ;
hooks . render . tap ( _pluginName , ( source , renderContext ) => {
2020-02-26 19:34:57 +08:00
const options = getOptionsForChunk ( renderContext . chunk ) ;
2020-02-20 03:25:49 +08:00
if ( options === false ) return source ;
return this . render ( source , renderContext , { options , compilation } ) ;
} ) ;
hooks . chunkHash . tap ( _pluginName , ( chunk , hash , context ) => {
2020-02-26 19:34:57 +08:00
const options = getOptionsForChunk ( chunk ) ;
2020-02-20 03:25:49 +08:00
if ( options === false ) return ;
this . chunkHash ( chunk , hash , context , { options , compilation } ) ;
} ) ;
} ) ;
}
/ * *
* @ param { LibraryOptions = } library normalized library option
* @ returns { T | false } preprocess as needed by overriding
* /
_parseOptionsCached ( library ) {
if ( ! library ) return false ;
if ( library . type !== this . _type ) return false ;
const cacheEntry = this . _parseCache . get ( library ) ;
if ( cacheEntry !== undefined ) return cacheEntry ;
const result = this . parseOptions ( library ) ;
this . _parseCache . set ( library , result ) ;
return result ;
}
2020-04-16 15:37:11 +08:00
/* istanbul ignore next */
2020-02-20 03:25:49 +08:00
/ * *
* @ abstract
* @ param { LibraryOptions } library normalized library option
* @ returns { T | false } preprocess as needed by overriding
* /
parseOptions ( library ) {
const AbstractMethodError = require ( "../AbstractMethodError" ) ;
throw new AbstractMethodError ( ) ;
}
/ * *
* @ param { Module } module the exporting entry module
2020-07-28 00:09:48 +08:00
* @ param { string } entryName the name of the entrypoint
2020-02-20 03:25:49 +08:00
* @ param { LibraryContext < T > } libraryContext context
* @ returns { void }
* /
2020-07-28 00:09:48 +08:00
finishEntryModule ( module , entryName , libraryContext ) { }
2020-02-20 03:25:49 +08:00
/ * *
* @ param { Chunk } chunk the chunk
* @ param { Set < string > } set runtime requirements
* @ param { LibraryContext < T > } libraryContext context
* @ returns { void }
* /
runtimeRequirements ( chunk , set , libraryContext ) {
set . add ( RuntimeGlobals . returnExportsFromRuntime ) ;
}
/ * *
* @ param { Source } source source
* @ param { RenderContext } renderContext render context
* @ param { LibraryContext < T > } libraryContext context
* @ returns { Source } source with library export
* /
render ( source , renderContext , libraryContext ) {
return source ;
}
/ * *
* @ param { Chunk } chunk the chunk
* @ param { Hash } hash hash
* @ param { ChunkHashContext } chunkHashContext chunk hash context
* @ param { LibraryContext < T > } libraryContext context
* @ returns { void }
* /
chunkHash ( chunk , hash , chunkHashContext , libraryContext ) {
const options = this . _parseOptionsCached (
libraryContext . compilation . outputOptions . library
) ;
hash . update ( this . _pluginName ) ;
hash . update ( JSON . stringify ( options ) ) ;
}
}
2021-02-05 06:11:11 +08:00
AbstractLibraryPlugin . COMMON _LIBRARY _NAME _MESSAGE = COMMON _LIBRARY _NAME _MESSAGE ;
2020-02-20 03:25:49 +08:00
module . exports = AbstractLibraryPlugin ;