123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- /*
- 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("../ChunkGraph")} ChunkGraph */
- /** @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("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */
- /** @typedef {import("../util/Hash")} Hash */
- 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]'.";
- /**
- * @template T
- * @typedef {object} LibraryContext
- * @property {Compilation} compilation
- * @property {ChunkGraph} chunkGraph
- * @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();
- }
- /**
- * Apply the plugin
- * @param {Compiler} compiler the compiler instance
- * @returns {void}
- */
- apply(compiler) {
- const { _pluginName } = this;
- compiler.hooks.thisCompilation.tap(_pluginName, compilation => {
- 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,
- compilation,
- chunkGraph: compilation.chunkGraph
- });
- }
- }
- }
- }
- }
- );
- /**
- * @param {Chunk} chunk chunk
- * @returns {TODO} options for the chunk
- */
- const getOptionsForChunk = chunk => {
- if (compilation.chunkGraph.getNumberOfEntryModules(chunk) === 0)
- return false;
- const options = chunk.getEntryOptions();
- const library = options && options.library;
- return this._parseOptionsCached(
- library !== undefined ? library : compilation.outputOptions.library
- );
- };
- if (
- this.render !== AbstractLibraryPlugin.prototype.render ||
- this.runtimeRequirements !==
- AbstractLibraryPlugin.prototype.runtimeRequirements
- ) {
- compilation.hooks.additionalChunkRuntimeRequirements.tap(
- _pluginName,
- (chunk, set, { chunkGraph }) => {
- const options = getOptionsForChunk(chunk);
- if (options !== false) {
- this.runtimeRequirements(chunk, set, {
- options,
- compilation,
- chunkGraph
- });
- }
- }
- );
- }
- const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation);
- if (this.render !== AbstractLibraryPlugin.prototype.render) {
- hooks.render.tap(_pluginName, (source, renderContext) => {
- const options = getOptionsForChunk(renderContext.chunk);
- if (options === false) return source;
- return this.render(source, renderContext, {
- options,
- compilation,
- chunkGraph: compilation.chunkGraph
- });
- });
- }
- 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,
- compilation,
- chunkGraph: compilation.chunkGraph
- });
- }
- );
- }
- 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,
- compilation,
- chunkGraph: compilation.chunkGraph
- });
- });
- }
- 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,
- compilation,
- chunkGraph: compilation.chunkGraph
- });
- }
- );
- }
- hooks.chunkHash.tap(_pluginName, (chunk, hash, context) => {
- const options = getOptionsForChunk(chunk);
- if (options === false) return;
- this.chunkHash(chunk, hash, context, {
- options,
- compilation,
- chunkGraph: compilation.chunkGraph
- });
- });
- });
- }
- /**
- * @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;
- }
- /* istanbul ignore next */
- /**
- * @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
- * @param {string} entryName the name of the entrypoint
- * @param {LibraryContext<T>} libraryContext context
- * @returns {void}
- */
- finishEntryModule(module, entryName, libraryContext) {}
- /**
- * @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;
- }
- /**
- * @param {RenderContext} renderContext render context
- * @param {LibraryContext<T>} libraryContext context
- * @returns {string | undefined} bailout reason
- */
- strictRuntimeBailout(renderContext, libraryContext) {
- return undefined;
- }
- /**
- * @param {Chunk} chunk the chunk
- * @param {Set<string>} set runtime requirements
- * @param {LibraryContext<T>} libraryContext context
- * @returns {void}
- */
- runtimeRequirements(chunk, set, libraryContext) {
- if (this.render !== AbstractLibraryPlugin.prototype.render)
- 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 {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;
- }
- /**
- * @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));
- }
- }
- AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE = COMMON_LIBRARY_NAME_MESSAGE;
- module.exports = AbstractLibraryPlugin;
|