| 
									
										
										
										
											2016-12-14 18:33:57 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Sean Larkin @thelarkinn | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | "use strict"; | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-06 22:59:11 +08:00
										 |  |  | const { find } = require("../util/SetHelpers"); | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | const AssetsOverSizeLimitWarning = require("./AssetsOverSizeLimitWarning"); | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | const EntrypointsOverSizeLimitWarning = require("./EntrypointsOverSizeLimitWarning"); | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | const NoAsyncChunksWarning = require("./NoAsyncChunksWarning"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 05:13:56 +08:00
										 |  |  | /** @typedef {import("webpack-sources").Source} Source */ | 
					
						
							|  |  |  | /** @typedef {import("../../declarations/WebpackOptions").PerformanceOptions} PerformanceOptions */ | 
					
						
							|  |  |  | /** @typedef {import("../ChunkGroup")} ChunkGroup */ | 
					
						
							|  |  |  | /** @typedef {import("../Compiler")} Compiler */ | 
					
						
							| 
									
										
										
										
											2019-09-11 17:13:46 +08:00
										 |  |  | /** @typedef {import("../Entrypoint")} Entrypoint */ | 
					
						
							| 
									
										
										
										
											2018-11-09 05:13:56 +08:00
										 |  |  | /** @typedef {import("../WebpackError")} WebpackError */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @typedef {Object} AssetDetails | 
					
						
							|  |  |  |  * @property {string} name | 
					
						
							|  |  |  |  * @property {number} size | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @typedef {Object} EntrypointDetails | 
					
						
							|  |  |  |  * @property {string} name | 
					
						
							|  |  |  |  * @property {number} size | 
					
						
							|  |  |  |  * @property {string[]} files | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | const isOverSizeLimitSet = new WeakSet(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-13 17:12:26 +08:00
										 |  |  | const excludeSourceMap = (name, source, info) => !info.development; | 
					
						
							| 
									
										
										
										
											2018-11-09 05:13:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | module.exports = class SizeLimitsPlugin { | 
					
						
							| 
									
										
										
										
											2018-11-09 05:13:56 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {PerformanceOptions} options the plugin options | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 	constructor(options) { | 
					
						
							|  |  |  | 		this.hints = options.hints; | 
					
						
							|  |  |  | 		this.maxAssetSize = options.maxAssetSize; | 
					
						
							|  |  |  | 		this.maxEntrypointSize = options.maxEntrypointSize; | 
					
						
							|  |  |  | 		this.assetFilter = options.assetFilter; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 05:13:56 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {ChunkGroup | Source} thing the resource to test | 
					
						
							|  |  |  | 	 * @returns {boolean} true if over the limit | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 	static isOverSizeLimit(thing) { | 
					
						
							|  |  |  | 		return isOverSizeLimitSet.has(thing); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 05:13:56 +08:00
										 |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2020-04-23 16:48:36 +08:00
										 |  |  | 	 * Apply the plugin | 
					
						
							| 
									
										
										
										
											2018-11-09 05:13:56 +08:00
										 |  |  | 	 * @param {Compiler} compiler the compiler instance | 
					
						
							|  |  |  | 	 * @returns {void} | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 	apply(compiler) { | 
					
						
							|  |  |  | 		const entrypointSizeLimit = this.maxEntrypointSize; | 
					
						
							|  |  |  | 		const assetSizeLimit = this.maxAssetSize; | 
					
						
							|  |  |  | 		const hints = this.hints; | 
					
						
							| 
									
										
										
										
											2018-11-09 05:13:56 +08:00
										 |  |  | 		const assetFilter = this.assetFilter || excludeSourceMap; | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 		compiler.hooks.afterEmit.tap("SizeLimitsPlugin", compilation => { | 
					
						
							| 
									
										
										
										
											2018-11-09 05:13:56 +08:00
										 |  |  | 			/** @type {WebpackError[]} */ | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 			const warnings = []; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 05:13:56 +08:00
										 |  |  | 			/** | 
					
						
							| 
									
										
										
										
											2019-09-11 17:13:46 +08:00
										 |  |  | 			 * @param {Entrypoint} entrypoint an entrypoint | 
					
						
							|  |  |  | 			 * @returns {number} the size of the entrypoint | 
					
						
							| 
									
										
										
										
											2018-11-09 05:13:56 +08:00
										 |  |  | 			 */ | 
					
						
							| 
									
										
										
										
											2020-01-20 21:41:39 +08:00
										 |  |  | 			const getEntrypointSize = entrypoint => { | 
					
						
							|  |  |  | 				let size = 0; | 
					
						
							|  |  |  | 				for (const file of entrypoint.getFiles()) { | 
					
						
							| 
									
										
										
										
											2019-09-11 17:13:46 +08:00
										 |  |  | 					const asset = compilation.getAsset(file); | 
					
						
							|  |  |  | 					if ( | 
					
						
							| 
									
										
										
										
											2019-09-13 12:37:33 +08:00
										 |  |  | 						asset && | 
					
						
							| 
									
										
										
										
											2019-09-11 17:13:46 +08:00
										 |  |  | 						assetFilter(asset.name, asset.source, asset.info) && | 
					
						
							|  |  |  | 						asset.source | 
					
						
							|  |  |  | 					) { | 
					
						
							| 
									
										
										
										
											2020-01-20 21:41:39 +08:00
										 |  |  | 						size += asset.info.size || asset.source.size(); | 
					
						
							| 
									
										
										
										
											2018-01-20 05:29:44 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2020-01-20 21:41:39 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				return size; | 
					
						
							|  |  |  | 			}; | 
					
						
							| 
									
										
										
										
											2016-12-14 18:33:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 05:13:56 +08:00
										 |  |  | 			/** @type {AssetDetails[]} */ | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 			const assetsOverSizeLimit = []; | 
					
						
							| 
									
										
										
										
											2019-09-11 17:13:46 +08:00
										 |  |  | 			for (const { name, source, info } of compilation.getAssets()) { | 
					
						
							|  |  |  | 				if (!assetFilter(name, source, info) || !source) { | 
					
						
							| 
									
										
										
										
											2018-01-22 20:52:43 +08:00
										 |  |  | 					continue; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-11 17:13:46 +08:00
										 |  |  | 				const size = info.size || source.size(); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				if (size > assetSizeLimit) { | 
					
						
							| 
									
										
										
										
											2018-01-22 20:52:43 +08:00
										 |  |  | 					assetsOverSizeLimit.push({ | 
					
						
							| 
									
										
										
										
											2019-09-11 17:13:46 +08:00
										 |  |  | 						name, | 
					
						
							|  |  |  | 						size | 
					
						
							| 
									
										
										
										
											2018-01-22 20:52:43 +08:00
										 |  |  | 					}); | 
					
						
							| 
									
										
										
										
											2019-09-13 17:12:26 +08:00
										 |  |  | 					isOverSizeLimitSet.add(source); | 
					
						
							| 
									
										
										
										
											2018-01-22 20:52:43 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-11 17:13:46 +08:00
										 |  |  | 			const fileFilter = name => { | 
					
						
							|  |  |  | 				const asset = compilation.getAsset(name); | 
					
						
							| 
									
										
										
										
											2019-09-13 21:28:43 +08:00
										 |  |  | 				return asset && assetFilter(asset.name, asset.source, asset.info); | 
					
						
							| 
									
										
										
										
											2019-09-11 17:13:46 +08:00
										 |  |  | 			}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 05:13:56 +08:00
										 |  |  | 			/** @type {EntrypointDetails[]} */ | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 			const entrypointsOverLimit = []; | 
					
						
							| 
									
										
										
										
											2019-09-11 17:13:46 +08:00
										 |  |  | 			for (const [name, entry] of compilation.entrypoints) { | 
					
						
							| 
									
										
										
										
											2018-03-29 13:08:43 +08:00
										 |  |  | 				const size = getEntrypointSize(entry); | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				if (size > entrypointSizeLimit) { | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 					entrypointsOverLimit.push({ | 
					
						
							|  |  |  | 						name: name, | 
					
						
							|  |  |  | 						size: size, | 
					
						
							| 
									
										
										
										
											2019-09-11 17:13:46 +08:00
										 |  |  | 						files: entry.getFiles().filter(fileFilter) | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 					}); | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 					isOverSizeLimitSet.add(entry); | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			if (hints) { | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 				// 1. Individual Chunk: Size < 250kb
 | 
					
						
							|  |  |  | 				// 2. Collective Initial Chunks [entrypoint] (Each Set?): Size < 250kb
 | 
					
						
							|  |  |  | 				// 3. No Async Chunks
 | 
					
						
							|  |  |  | 				// if !1, then 2, if !2 return
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				if (assetsOverSizeLimit.length > 0) { | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 					warnings.push( | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						new AssetsOverSizeLimitWarning(assetsOverSizeLimit, assetSizeLimit) | 
					
						
							|  |  |  | 					); | 
					
						
							| 
									
										
										
										
											2016-12-14 18:33:57 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				if (entrypointsOverLimit.length > 0) { | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 					warnings.push( | 
					
						
							|  |  |  | 						new EntrypointsOverSizeLimitWarning( | 
					
						
							|  |  |  | 							entrypointsOverLimit, | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							entrypointSizeLimit | 
					
						
							|  |  |  | 						) | 
					
						
							|  |  |  | 					); | 
					
						
							| 
									
										
										
										
											2016-12-14 18:33:57 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				if (warnings.length > 0) { | 
					
						
							| 
									
										
										
										
											2018-09-06 22:59:11 +08:00
										 |  |  | 					const someAsyncChunk = find( | 
					
						
							|  |  |  | 						compilation.chunks, | 
					
						
							|  |  |  | 						chunk => !chunk.canBeInitial() | 
					
						
							|  |  |  | 					); | 
					
						
							| 
									
										
										
										
											2016-12-14 18:33:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-06 22:59:11 +08:00
										 |  |  | 					if (!someAsyncChunk) { | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 						warnings.push(new NoAsyncChunksWarning()); | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2016-12-14 18:33:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					if (hints === "error") { | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 						compilation.errors.push(...warnings); | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 					} else { | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 						compilation.warnings.push(...warnings); | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2016-12-14 18:33:57 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 		}); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-14 18:33:57 +08:00
										 |  |  | }; |