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 */
2021-04-09 21:50:25 +08:00
/** @typedef {import("../ChunkGraph")} ChunkGraph */
2020-02-20 03:25:49 +08:00
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
2021-02-05 06:17:20 +08:00
/** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */
2020-02-20 03:25:49 +08:00
/** @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
2024-06-11 21:09:50 +08:00
* @ typedef { object } LibraryContext
2020-02-20 03:25:49 +08:00
* @ property { Compilation } compilation
2021-04-09 21:50:25 +08:00
* @ property { ChunkGraph } chunkGraph
2020-02-20 03:25:49 +08:00
* @ property { T } options
* /
2025-04-03 00:02:22 +08:00
/ * *
* @ typedef { object } AbstractLibraryPluginOptions
* @ property { string } pluginName name of the plugin
* @ property { LibraryType } type used library type
* /
2020-02-20 03:25:49 +08:00
/ * *
* @ template T
* /
class AbstractLibraryPlugin {
/ * *
2025-04-03 00:02:22 +08:00
* @ param { AbstractLibraryPluginOptions } options options
2020-02-20 03:25:49 +08:00
* /
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 => {
2021-02-05 06:17:20 +08:00
compilation . hooks . finishModules . tap (
{ name : _pluginName , stage : 10 } ,
( ) => {
for ( const [
name ,
{
dependencies : deps ,
options : { library }
}
] of compilation . entries ) {
const options = this . _parseOptionsCached (
library !== undefined
? library
: compilation . outputOptions . library
) ;
if ( options !== false ) {
const dep = deps [ deps . length - 1 ] ;
if ( dep ) {
const module = compilation . moduleGraph . getModule ( dep ) ;
if ( module ) {
this . finishEntryModule ( module , name , {
options ,
2021-04-09 21:50:25 +08:00
compilation ,
chunkGraph : compilation . chunkGraph
2021-02-05 06:17:20 +08:00
} ) ;
}
2020-02-20 03:25:49 +08:00
}
}
}
}
2021-02-05 06:17:20 +08:00
) ;
2020-02-20 03:25:49 +08:00
2023-05-25 06:09:00 +08:00
/ * *
* @ param { Chunk } chunk chunk
* @ returns { TODO } options for the chunk
* /
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
) ;
} ;
2021-02-05 06:17:20 +08:00
if (
this . render !== AbstractLibraryPlugin . prototype . render ||
this . runtimeRequirements !==
AbstractLibraryPlugin . prototype . runtimeRequirements
) {
compilation . hooks . additionalChunkRuntimeRequirements . tap (
_pluginName ,
2021-04-09 21:50:25 +08:00
( chunk , set , { chunkGraph } ) => {
2021-02-05 06:17:20 +08:00
const options = getOptionsForChunk ( chunk ) ;
if ( options !== false ) {
2021-04-09 21:50:25 +08:00
this . runtimeRequirements ( chunk , set , {
options ,
compilation ,
chunkGraph
} ) ;
2021-02-05 06:17:20 +08:00
}
2020-02-20 03:25:49 +08:00
}
2021-02-05 06:17:20 +08:00
) ;
}
2020-02-20 03:25:49 +08:00
const hooks = JavascriptModulesPlugin . getCompilationHooks ( compilation ) ;
2021-02-05 06:17:20 +08:00
if ( this . render !== AbstractLibraryPlugin . prototype . render ) {
hooks . render . tap ( _pluginName , ( source , renderContext ) => {
const options = getOptionsForChunk ( renderContext . chunk ) ;
if ( options === false ) return source ;
2021-04-09 21:50:25 +08:00
return this . render ( source , renderContext , {
options ,
compilation ,
chunkGraph : compilation . chunkGraph
} ) ;
2021-02-05 06:17:20 +08:00
} ) ;
}
2021-02-11 02:14:50 +08:00
if (
this . embedInRuntimeBailout !==
AbstractLibraryPlugin . prototype . embedInRuntimeBailout
) {
hooks . embedInRuntimeBailout . tap (
_pluginName ,
( module , renderContext ) => {
const options = getOptionsForChunk ( renderContext . chunk ) ;
if ( options === false ) return ;
return this . embedInRuntimeBailout ( module , renderContext , {
options ,
2021-04-09 21:50:25 +08:00
compilation ,
chunkGraph : compilation . chunkGraph
2021-02-11 02:14:50 +08:00
} ) ;
}
) ;
}
2021-03-15 23:37:19 +08:00
if (
this . strictRuntimeBailout !==
AbstractLibraryPlugin . prototype . strictRuntimeBailout
) {
hooks . strictRuntimeBailout . tap ( _pluginName , renderContext => {
const options = getOptionsForChunk ( renderContext . chunk ) ;
if ( options === false ) return ;
return this . strictRuntimeBailout ( renderContext , {
options ,
2021-04-09 21:50:25 +08:00
compilation ,
chunkGraph : compilation . chunkGraph
2021-03-15 23:37:19 +08:00
} ) ;
} ) ;
}
2021-02-05 06:17:20 +08:00
if (
this . renderStartup !== AbstractLibraryPlugin . prototype . renderStartup
) {
hooks . renderStartup . tap (
_pluginName ,
( source , module , renderContext ) => {
const options = getOptionsForChunk ( renderContext . chunk ) ;
if ( options === false ) return source ;
return this . renderStartup ( source , module , renderContext , {
options ,
2021-04-09 21:50:25 +08:00
compilation ,
chunkGraph : compilation . chunkGraph
2021-02-05 06:17:20 +08:00
} ) ;
}
) ;
}
2020-02-20 03:25:49 +08:00
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 ;
2021-04-09 21:50:25 +08:00
this . chunkHash ( chunk , hash , context , {
options ,
compilation ,
chunkGraph : compilation . chunkGraph
} ) ;
2020-02-20 03:25:49 +08:00
} ) ;
} ) ;
}
/ * *
* @ 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
2021-02-11 02:14:50 +08:00
/ * *
* @ param { Module } module the exporting entry module
* @ param { RenderContext } renderContext render context
* @ param { LibraryContext < T > } libraryContext context
* @ returns { string | undefined } bailout reason
* /
embedInRuntimeBailout ( module , renderContext , libraryContext ) {
return undefined ;
}
2021-03-15 23:37:19 +08:00
/ * *
* @ param { RenderContext } renderContext render context
* @ param { LibraryContext < T > } libraryContext context
* @ returns { string | undefined } bailout reason
* /
strictRuntimeBailout ( renderContext , libraryContext ) {
return undefined ;
}
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 ) {
2021-02-05 06:17:20 +08:00
if ( this . render !== AbstractLibraryPlugin . prototype . render )
set . add ( RuntimeGlobals . returnExportsFromRuntime ) ;
2020-02-20 03:25:49 +08:00
}
/ * *
* @ 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 ;
}
2021-02-05 06:17:20 +08:00
/ * *
* @ param { Source } source source
* @ param { Module } module module
* @ param { StartupRenderContext } renderContext render context
* @ param { LibraryContext < T > } libraryContext context
* @ returns { Source } source with library export
* /
renderStartup ( source , module , renderContext , libraryContext ) {
return source ;
}
2020-02-20 03:25:49 +08:00
/ * *
* @ 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 ;