| | |
| | | ASSET_MODULE_TYPE_RESOURCE, |
| | | ASSET_MODULE_TYPE_SOURCE |
| | | } = require("../ModuleTypeConstants"); |
| | | const { compareModulesByIdOrIdentifier } = require("../util/comparators"); |
| | | const createSchemaValidation = require("../util/create-schema-validation"); |
| | | const { compareModulesByFullName } = require("../util/comparators"); |
| | | const memoize = require("../util/memoize"); |
| | | |
| | | /** @typedef {import("webpack-sources").Source} Source */ |
| | | /** @typedef {import("schema-utils").Schema} Schema */ |
| | | /** @typedef {import("../../declarations/WebpackOptions").AssetGeneratorDataUrl} AssetGeneratorDataUrl */ |
| | | /** @typedef {import("../../declarations/WebpackOptions").AssetModuleOutputPath} AssetModuleOutputPath */ |
| | | /** @typedef {import("../../declarations/WebpackOptions").RawPublicPath} RawPublicPath */ |
| | | /** @typedef {import("../../declarations/WebpackOptions").FilenameTemplate} FilenameTemplate */ |
| | | /** @typedef {import("../Compilation").AssetInfo} AssetInfo */ |
| | | /** @typedef {import("../Compiler")} Compiler */ |
| | | /** @typedef {import("../Module").BuildInfo} BuildInfo */ |
| | | /** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */ |
| | | /** @typedef {import("../NormalModule")} NormalModule */ |
| | | /** @typedef {import("../NormalModule").NormalModuleCreateData} NormalModuleCreateData */ |
| | | |
| | | /** |
| | | * Returns definition. |
| | | * @param {string} name name of definitions |
| | | * @returns {Schema} definition |
| | | */ |
| | |
| | | name: "Asset Modules Plugin", |
| | | baseDataPath: "generator" |
| | | }; |
| | | const validateGeneratorOptions = { |
| | | asset: createSchemaValidation( |
| | | require("../../schemas/plugins/asset/AssetGeneratorOptions.check"), |
| | | () => getSchema("AssetGeneratorOptions"), |
| | | generatorValidationOptions |
| | | ), |
| | | "asset/resource": createSchemaValidation( |
| | | require("../../schemas/plugins/asset/AssetResourceGeneratorOptions.check"), |
| | | () => getSchema("AssetResourceGeneratorOptions"), |
| | | generatorValidationOptions |
| | | ), |
| | | "asset/inline": createSchemaValidation( |
| | | require("../../schemas/plugins/asset/AssetInlineGeneratorOptions.check"), |
| | | () => getSchema("AssetInlineGeneratorOptions"), |
| | | generatorValidationOptions |
| | | ) |
| | | }; |
| | | |
| | | const validateParserOptions = createSchemaValidation( |
| | | require("../../schemas/plugins/asset/AssetParserOptions.check"), |
| | | () => getSchema("AssetParserOptions"), |
| | | { |
| | | name: "Asset Modules Plugin", |
| | | baseDataPath: "parser" |
| | | } |
| | | ); |
| | | |
| | | const getAssetGenerator = memoize(() => require("./AssetGenerator")); |
| | | const getAssetParser = memoize(() => require("./AssetParser")); |
| | |
| | | require("./AssetSourceGenerator") |
| | | ); |
| | | const getAssetBytesGenerator = memoize(() => require("./AssetBytesGenerator")); |
| | | const getNormalModule = memoize(() => require("../NormalModule")); |
| | | |
| | | const type = ASSET_MODULE_TYPE; |
| | | const PLUGIN_NAME = "AssetModulesPlugin"; |
| | | |
| | | /** |
| | | * Represents the asset modules plugin runtime component. |
| | | * @typedef {object} AssetModulesPluginOptions |
| | | * @property {boolean=} sideEffectFree |
| | | */ |
| | | |
| | | class AssetModulesPlugin { |
| | | /** |
| | | * Apply the plugin |
| | | * Creates an instance of AssetModulesPlugin. |
| | | * @param {AssetModulesPluginOptions} options options |
| | | */ |
| | | constructor(options) { |
| | | this.options = options; |
| | | } |
| | | |
| | | /** |
| | | * Applies the plugin by registering its hooks on the compiler. |
| | | * @param {Compiler} compiler the compiler instance |
| | | * @returns {void} |
| | | */ |
| | |
| | | compiler.hooks.compilation.tap( |
| | | PLUGIN_NAME, |
| | | (compilation, { normalModuleFactory }) => { |
| | | const NormalModule = getNormalModule(); |
| | | for (const type of [ |
| | | ASSET_MODULE_TYPE, |
| | | ASSET_MODULE_TYPE_BYTES, |
| | | ASSET_MODULE_TYPE_INLINE, |
| | | ASSET_MODULE_TYPE_RESOURCE, |
| | | ASSET_MODULE_TYPE_SOURCE |
| | | ]) { |
| | | normalModuleFactory.hooks.createModuleClass |
| | | .for(type) |
| | | .tap(PLUGIN_NAME, (createData, _resolveData) => { |
| | | // TODO create the module via new AssetModule with its own properties |
| | | const module = new NormalModule( |
| | | /** @type {NormalModuleCreateData} */ |
| | | (createData) |
| | | ); |
| | | if (this.options.sideEffectFree) { |
| | | module.factoryMeta = { sideEffectFree: true }; |
| | | } |
| | | |
| | | return module; |
| | | }); |
| | | } |
| | | |
| | | normalModuleFactory.hooks.createParser |
| | | .for(ASSET_MODULE_TYPE) |
| | | .tap(PLUGIN_NAME, (parserOptions) => { |
| | | validateParserOptions(parserOptions); |
| | | compiler.validate( |
| | | () => getSchema("AssetParserOptions"), |
| | | parserOptions, |
| | | { |
| | | name: "Asset Modules Plugin", |
| | | baseDataPath: "parser" |
| | | }, |
| | | (options) => |
| | | require("../../schemas/plugins/asset/AssetParserOptions.check")( |
| | | options |
| | | ) |
| | | ); |
| | | |
| | | let dataUrlCondition = parserOptions.dataUrlCondition; |
| | | if (!dataUrlCondition || typeof dataUrlCondition === "object") { |
| | |
| | | normalModuleFactory.hooks.createGenerator |
| | | .for(type) |
| | | .tap(PLUGIN_NAME, (generatorOptions) => { |
| | | validateGeneratorOptions[type](generatorOptions); |
| | | switch (type) { |
| | | case ASSET_MODULE_TYPE: { |
| | | compiler.validate( |
| | | () => getSchema("AssetGeneratorOptions"), |
| | | generatorOptions, |
| | | generatorValidationOptions, |
| | | (options) => |
| | | require("../../schemas/plugins/asset/AssetGeneratorOptions.check")( |
| | | options |
| | | ) |
| | | ); |
| | | break; |
| | | } |
| | | case ASSET_MODULE_TYPE_RESOURCE: { |
| | | compiler.validate( |
| | | () => getSchema("AssetResourceGeneratorOptions"), |
| | | generatorOptions, |
| | | generatorValidationOptions, |
| | | (options) => |
| | | require("../../schemas/plugins/asset/AssetResourceGeneratorOptions.check")( |
| | | options |
| | | ) |
| | | ); |
| | | break; |
| | | } |
| | | case ASSET_MODULE_TYPE_INLINE: { |
| | | compiler.validate( |
| | | () => getSchema("AssetInlineGeneratorOptions"), |
| | | generatorOptions, |
| | | generatorValidationOptions, |
| | | (options) => |
| | | require("../../schemas/plugins/asset/AssetInlineGeneratorOptions.check")( |
| | | options |
| | | ) |
| | | ); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | /** @type {undefined | AssetGeneratorDataUrl} */ |
| | | let dataUrl; |
| | | if (type !== ASSET_MODULE_TYPE_RESOURCE) { |
| | | dataUrl = generatorOptions.dataUrl; |
| | |
| | | } |
| | | } |
| | | |
| | | /** @type {undefined | FilenameTemplate} */ |
| | | let filename; |
| | | /** @type {undefined | RawPublicPath} */ |
| | | let publicPath; |
| | | /** @type {undefined | AssetModuleOutputPath} */ |
| | | let outputPath; |
| | | if (type !== ASSET_MODULE_TYPE_INLINE) { |
| | | filename = generatorOptions.filename; |
| | |
| | | const modules = chunkGraph.getOrderedChunkModulesIterableBySourceType( |
| | | chunk, |
| | | ASSET_MODULE_TYPE, |
| | | compareModulesByIdOrIdentifier(chunkGraph) |
| | | compareModulesByFullName(compilation.compiler) |
| | | ); |
| | | if (modules) { |
| | | for (const module of modules) { |