| 
									
										
										
										
											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 */ | 
					
						
							|  |  |  | /** @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(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 05:13:56 +08:00
										 |  |  | const excludeSourceMap = asset => !asset.endsWith(".map"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @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
										 |  |  | 			/** | 
					
						
							|  |  |  | 			 * @param {ChunkGroup} entrypoint the entrypoint | 
					
						
							|  |  |  | 			 * @returns {number} its calculated size | 
					
						
							|  |  |  | 			 */ | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 			const getEntrypointSize = entrypoint => | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				entrypoint.getFiles().reduce((currentSize, file) => { | 
					
						
							|  |  |  | 					if (assetFilter(file) && compilation.assets[file]) { | 
					
						
							| 
									
										
										
										
											2018-01-20 05:29:44 +08:00
										 |  |  | 						return currentSize + compilation.assets[file].size(); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					return currentSize; | 
					
						
							|  |  |  | 				}, 0); | 
					
						
							| 
									
										
										
										
											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 = []; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			for (const assetName of Object.keys(compilation.assets)) { | 
					
						
							|  |  |  | 				if (!assetFilter(assetName)) { | 
					
						
							| 
									
										
										
										
											2018-01-22 20:52:43 +08:00
										 |  |  | 					continue; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				const asset = compilation.assets[assetName]; | 
					
						
							|  |  |  | 				const size = asset.size(); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				if (size > assetSizeLimit) { | 
					
						
							| 
									
										
										
										
											2018-01-22 20:52:43 +08:00
										 |  |  | 					assetsOverSizeLimit.push({ | 
					
						
							|  |  |  | 						name: assetName, | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						size: size | 
					
						
							| 
									
										
										
										
											2018-01-22 20:52:43 +08:00
										 |  |  | 					}); | 
					
						
							| 
									
										
										
										
											2018-08-14 17:18:22 +08:00
										 |  |  | 					isOverSizeLimitSet.add(asset); | 
					
						
							| 
									
										
										
										
											2018-01-22 20:52:43 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 05:13:56 +08:00
										 |  |  | 			/** @type {EntrypointDetails[]} */ | 
					
						
							| 
									
										
										
										
											2017-01-04 03:21:51 +08:00
										 |  |  | 			const entrypointsOverLimit = []; | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			for (const pair of compilation.entrypoints) { | 
					
						
							| 
									
										
										
										
											2018-01-20 00:06:59 +08:00
										 |  |  | 				const name = pair[0]; | 
					
						
							|  |  |  | 				const entry = pair[1]; | 
					
						
							| 
									
										
										
										
											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, | 
					
						
							|  |  |  | 						files: entry.getFiles().filter(assetFilter) | 
					
						
							|  |  |  | 					}); | 
					
						
							| 
									
										
										
										
											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
										 |  |  | }; |