| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 | /*	MIT License http://www.opensource.org/licenses/mit-license.php	Author Yuta Hiroto @hiroppy*/"use strict";const {	ASSET_MODULE_TYPE,	ASSET_MODULE_TYPE_INLINE,	ASSET_MODULE_TYPE_RESOURCE,	ASSET_MODULE_TYPE_SOURCE} = require("../ModuleTypeConstants");const { cleverMerge } = require("../util/cleverMerge");const { compareModulesByIdOrIdentifier } = require("../util/comparators");const createSchemaValidation = require("../util/create-schema-validation");const memoize = require("../util/memoize");/** @typedef {import("webpack-sources").Source} Source *//** @typedef {import("../../declarations/WebpackOptions").AssetParserOptions} AssetParserOptions *//** @typedef {import("schema-utils").Schema} Schema *//** @typedef {import("../Chunk")} Chunk *//** @typedef {import("../Compilation").AssetInfo} AssetInfo *//** @typedef {import("../Compiler")} Compiler *//** @typedef {import("../Module")} Module *//** @typedef {import("../Module").BuildInfo} BuildInfo *//** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult *//** @typedef {import("../NormalModule")} NormalModule *//** * @param {string} name name of definitions * @returns {Schema} definition */const getSchema = name => {	const { definitions } = require("../../schemas/WebpackOptions.json");	return {		definitions,		oneOf: [{ $ref: `#/definitions/${name}` }]	};};const generatorValidationOptions = {	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"));const getAssetSourceParser = memoize(() => require("./AssetSourceParser"));const getAssetSourceGenerator = memoize(() =>	require("./AssetSourceGenerator"));const type = ASSET_MODULE_TYPE;const PLUGIN_NAME = "AssetModulesPlugin";class AssetModulesPlugin {	/**	 * Apply the plugin	 * @param {Compiler} compiler the compiler instance	 * @returns {void}	 */	apply(compiler) {		compiler.hooks.compilation.tap(			PLUGIN_NAME,			(compilation, { normalModuleFactory }) => {				normalModuleFactory.hooks.createParser					.for(ASSET_MODULE_TYPE)					.tap(PLUGIN_NAME, parserOptions => {						validateParserOptions(parserOptions);						parserOptions = cleverMerge(							/** @type {AssetParserOptions} */							(compiler.options.module.parser.asset),							parserOptions						);						let dataUrlCondition = parserOptions.dataUrlCondition;						if (!dataUrlCondition || typeof dataUrlCondition === "object") {							dataUrlCondition = {								maxSize: 8096,								...dataUrlCondition							};						}						const AssetParser = getAssetParser();						return new AssetParser(dataUrlCondition);					});				normalModuleFactory.hooks.createParser					.for(ASSET_MODULE_TYPE_INLINE)					.tap(PLUGIN_NAME, _parserOptions => {						const AssetParser = getAssetParser();						return new AssetParser(true);					});				normalModuleFactory.hooks.createParser					.for(ASSET_MODULE_TYPE_RESOURCE)					.tap(PLUGIN_NAME, _parserOptions => {						const AssetParser = getAssetParser();						return new AssetParser(false);					});				normalModuleFactory.hooks.createParser					.for(ASSET_MODULE_TYPE_SOURCE)					.tap(PLUGIN_NAME, _parserOptions => {						const AssetSourceParser = getAssetSourceParser();						return new AssetSourceParser();					});				for (const type of [					ASSET_MODULE_TYPE,					ASSET_MODULE_TYPE_INLINE,					ASSET_MODULE_TYPE_RESOURCE				]) {					normalModuleFactory.hooks.createGenerator						.for(type)						.tap(PLUGIN_NAME, generatorOptions => {							validateGeneratorOptions[type](generatorOptions);							let dataUrl;							if (type !== ASSET_MODULE_TYPE_RESOURCE) {								dataUrl = generatorOptions.dataUrl;								if (!dataUrl || typeof dataUrl === "object") {									dataUrl = {										encoding: undefined,										mimetype: undefined,										...dataUrl									};								}							}							let filename;							let publicPath;							let outputPath;							if (type !== ASSET_MODULE_TYPE_INLINE) {								filename = generatorOptions.filename;								publicPath = generatorOptions.publicPath;								outputPath = generatorOptions.outputPath;							}							const AssetGenerator = getAssetGenerator();							return new AssetGenerator(								compilation.moduleGraph,								dataUrl,								filename,								publicPath,								outputPath,								generatorOptions.emit !== false							);						});				}				normalModuleFactory.hooks.createGenerator					.for(ASSET_MODULE_TYPE_SOURCE)					.tap(PLUGIN_NAME, () => {						const AssetSourceGenerator = getAssetSourceGenerator();						return new AssetSourceGenerator(compilation.moduleGraph);					});				compilation.hooks.renderManifest.tap(PLUGIN_NAME, (result, options) => {					const { chunkGraph } = compilation;					const { chunk, codeGenerationResults, runtimeTemplate } = options;					const modules = chunkGraph.getOrderedChunkModulesIterableBySourceType(						chunk,						ASSET_MODULE_TYPE,						compareModulesByIdOrIdentifier(chunkGraph)					);					if (modules) {						for (const module of modules) {							try {								const codeGenResult = codeGenerationResults.get(									module,									chunk.runtime								);								const buildInfo = /** @type {BuildInfo} */ (module.buildInfo);								const data =									/** @type {NonNullable<CodeGenerationResult["data"]>} */									(codeGenResult.data);								const errored = module.getNumberOfErrors() > 0;								/** @type {string} */								let entryFilename;								/** @type {AssetInfo} */								let entryInfo;								/** @type {string} */								let entryHash;								if (errored) {									const erroredModule = /** @type {NormalModule} */ (module);									const AssetGenerator = getAssetGenerator();									const [fullContentHash, contentHash] =										AssetGenerator.getFullContentHash(											erroredModule,											runtimeTemplate										);									const { filename, assetInfo } =										AssetGenerator.getFilenameWithInfo(											erroredModule,											{												filename:													erroredModule.generatorOptions &&													erroredModule.generatorOptions.filename,												outputPath:													erroredModule.generatorOptions &&													erroredModule.generatorOptions.outputPath											},											{												runtime: chunk.runtime,												runtimeTemplate,												chunkGraph											},											contentHash										);									entryFilename = filename;									entryInfo = assetInfo;									entryHash = fullContentHash;								} else {									entryFilename = buildInfo.filename || data.get("filename");									entryInfo = buildInfo.assetInfo || data.get("assetInfo");									entryHash =										buildInfo.fullContentHash || data.get("fullContentHash");								}								result.push({									render: () =>										/** @type {Source} */ (codeGenResult.sources.get(type)),									filename: entryFilename,									info: entryInfo,									auxiliary: true,									identifier: `assetModule${chunkGraph.getModuleId(module)}`,									hash: entryHash								});							} catch (err) {								/** @type {Error} */ (err).message +=									`\nduring rendering of asset ${module.identifier()}`;								throw err;							}						}					}					return result;				});				compilation.hooks.prepareModuleExecution.tap(					PLUGIN_NAME,					(options, context) => {						const { codeGenerationResult } = options;						const source = codeGenerationResult.sources.get(ASSET_MODULE_TYPE);						if (source === undefined) return;						const data =							/** @type {NonNullable<CodeGenerationResult["data"]>} */							(codeGenerationResult.data);						context.assets.set(data.get("filename"), {							source,							info: data.get("assetInfo")						});					}				);			}		);	}}module.exports = AssetModulesPlugin;
 |