mirror of https://github.com/webpack/webpack.git
				
				
				
			Merge 5197fd7f03 into e1afcd4cc2
				
					
				
			This commit is contained in:
		
						commit
						5b6d7ba0c3
					
				| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file was automatically generated.
 | 
				
			||||||
 | 
					 * DO NOT MODIFY BY HAND.
 | 
				
			||||||
 | 
					 * Run `yarn fix:special` to update
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ManifestPluginOptions {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Specifies the filename of the output file on disk. By default the plugin will emit `manifest.json` inside the 'output.path' directory.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						filename?: string;
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * A custom Function to create the manifest.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						handle?: (
 | 
				
			||||||
 | 
							manifest: Record<string, string>,
 | 
				
			||||||
 | 
							stats: import("../../lib/stats/DefaultStatsFactoryPlugin").StatsCompilation
 | 
				
			||||||
 | 
						) => string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,149 @@
 | 
				
			||||||
 | 
					This example demonstrates how to use webpack internal ManifestPlugin.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# example.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					import("./baz");
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# foo.txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					foo
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# bar.txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					bar
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# baz.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					import foo from "./foo.txt";
 | 
				
			||||||
 | 
					import bar from "./bar.txt";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default foo + bar;
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# webpack.config.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```javascript
 | 
				
			||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const webpack = require("../../");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @type {webpack.Configuration} */
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						devtool: "source-map",
 | 
				
			||||||
 | 
						module: {
 | 
				
			||||||
 | 
							rules: [
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									test: /foo.txt/,
 | 
				
			||||||
 | 
									type: "asset/resource"
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									test: /bar.txt/,
 | 
				
			||||||
 | 
									use: require.resolve("file-loader")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						plugins: [
 | 
				
			||||||
 | 
							new webpack.ManifestPlugin({
 | 
				
			||||||
 | 
								filename: "manifest.json"
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
							new webpack.ManifestPlugin({
 | 
				
			||||||
 | 
								filename: "manifest.yml",
 | 
				
			||||||
 | 
								handle(manifest) {
 | 
				
			||||||
 | 
									let _manifest = "";
 | 
				
			||||||
 | 
									for (const key in manifest) {
 | 
				
			||||||
 | 
										if (key === "manifest.json") continue;
 | 
				
			||||||
 | 
										_manifest += `- ${key}: '${manifest[key]}'\n`;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return _manifest;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						]
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# dist/manifest.json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```json
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "output.js.map": "dist/output.js.map",
 | 
				
			||||||
 | 
					  "main.js": "dist/output.js",
 | 
				
			||||||
 | 
					  "bar.txt": "dist/a0145fafc7fab801e574631452de554b.txt",
 | 
				
			||||||
 | 
					  "foo.txt": "dist/3ee037f347c64cc372ad.txt",
 | 
				
			||||||
 | 
					  "1.output.js.map": "dist/1.output.js.map",
 | 
				
			||||||
 | 
					  "1.output.js": "dist/1.output.js"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# dist/manifest.yml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```yml
 | 
				
			||||||
 | 
					- output.js.map: 'dist/output.js.map'
 | 
				
			||||||
 | 
					- main.js: 'dist/output.js'
 | 
				
			||||||
 | 
					- bar.txt: 'dist/a0145fafc7fab801e574631452de554b.txt'
 | 
				
			||||||
 | 
					- foo.txt: 'dist/3ee037f347c64cc372ad.txt'
 | 
				
			||||||
 | 
					- 1.output.js.map: 'dist/1.output.js.map'
 | 
				
			||||||
 | 
					- 1.output.js: 'dist/1.output.js'
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Unoptimized
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					assets by path *.js 11.9 KiB
 | 
				
			||||||
 | 
					  asset output.js 9.61 KiB [emitted] (name: main) 1 related asset
 | 
				
			||||||
 | 
					  asset 1.output.js 2.3 KiB [emitted] 1 related asset
 | 
				
			||||||
 | 
					assets by path *.txt 8 bytes
 | 
				
			||||||
 | 
					  asset 3ee037f347c64cc372ad.txt 4 bytes [emitted] [immutable] [from: foo.txt]
 | 
				
			||||||
 | 
					  asset a0145fafc7fab801e574631452de554b.txt 4 bytes [emitted] [immutable] [from: bar.txt]
 | 
				
			||||||
 | 
					asset manifest.json 260 bytes [emitted]
 | 
				
			||||||
 | 
					asset manifest.yml 240 bytes [emitted]
 | 
				
			||||||
 | 
					chunk (runtime: main) output.js (main) 17 bytes (javascript) 5.48 KiB (runtime) [entry] [rendered]
 | 
				
			||||||
 | 
					  > ./example.js main
 | 
				
			||||||
 | 
					  runtime modules 5.48 KiB 8 modules
 | 
				
			||||||
 | 
					  ./example.js 17 bytes [built] [code generated]
 | 
				
			||||||
 | 
					    [used exports unknown]
 | 
				
			||||||
 | 
					    entry ./example.js main
 | 
				
			||||||
 | 
					chunk (runtime: main) 1.output.js 207 bytes (javascript) 4 bytes (asset) [rendered]
 | 
				
			||||||
 | 
					  > ./baz ./example.js 1:0-15
 | 
				
			||||||
 | 
					  dependent modules 122 bytes (javascript) 4 bytes (asset) [dependent] 2 modules
 | 
				
			||||||
 | 
					  ./baz.js 85 bytes [built] [code generated]
 | 
				
			||||||
 | 
					    [exports: default]
 | 
				
			||||||
 | 
					    [used exports unknown]
 | 
				
			||||||
 | 
					    import() ./baz ./example.js 1:0-15
 | 
				
			||||||
 | 
					webpack X.X.X compiled successfully
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Production mode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					assets by path *.js 2.17 KiB
 | 
				
			||||||
 | 
					  asset output.js 1.94 KiB [emitted] [minimized] (name: main) 1 related asset
 | 
				
			||||||
 | 
					  asset 293.output.js 237 bytes [emitted] [minimized] 1 related asset
 | 
				
			||||||
 | 
					assets by path *.txt 8 bytes
 | 
				
			||||||
 | 
					  asset 3ee037f347c64cc372ad.txt 4 bytes [emitted] [immutable] [from: foo.txt]
 | 
				
			||||||
 | 
					  asset a0145fafc7fab801e574631452de554b.txt 4 bytes [emitted] [immutable] [from: bar.txt]
 | 
				
			||||||
 | 
					asset manifest.json 268 bytes [emitted]
 | 
				
			||||||
 | 
					asset manifest.yml 248 bytes [emitted]
 | 
				
			||||||
 | 
					chunk (runtime: main) 293.output.js 4 bytes (asset) 249 bytes (javascript) [rendered]
 | 
				
			||||||
 | 
					  > ./baz ./example.js 1:0-15
 | 
				
			||||||
 | 
					  ./baz.js + 2 modules 207 bytes [built] [code generated]
 | 
				
			||||||
 | 
					    [exports: default]
 | 
				
			||||||
 | 
					    import() ./baz ./example.js 1:0-15
 | 
				
			||||||
 | 
					  ./foo.txt 4 bytes (asset) 42 bytes (javascript) [built] [code generated]
 | 
				
			||||||
 | 
					    [no exports]
 | 
				
			||||||
 | 
					chunk (runtime: main) output.js (main) 17 bytes (javascript) 5.48 KiB (runtime) [entry] [rendered]
 | 
				
			||||||
 | 
					  > ./example.js main
 | 
				
			||||||
 | 
					  runtime modules 5.48 KiB 8 modules
 | 
				
			||||||
 | 
					  ./example.js 17 bytes [built] [code generated]
 | 
				
			||||||
 | 
					    [no exports used]
 | 
				
			||||||
 | 
					    entry ./example.js main
 | 
				
			||||||
 | 
					webpack X.X.X compiled successfully
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					bar
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,4 @@
 | 
				
			||||||
 | 
					import foo from "./foo.txt";
 | 
				
			||||||
 | 
					import bar from "./bar.txt";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default foo + bar;
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					require("../build-common");
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					import("./baz");
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					foo
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,57 @@
 | 
				
			||||||
 | 
					This example demonstrates how to use webpack internal ManifestPlugin.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# example.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					_{{example.js}}_
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# foo.txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					_{{foo.txt}}_
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# bar.txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					_{{bar.txt}}_
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# baz.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					_{{baz.js}}_
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# webpack.config.js
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```javascript
 | 
				
			||||||
 | 
					_{{webpack.config.js}}_
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# dist/manifest.json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```json
 | 
				
			||||||
 | 
					_{{dist/manifest.json}}_
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# dist/manifest.yml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```yml
 | 
				
			||||||
 | 
					_{{dist/manifest.yml}}_
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Info
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Unoptimized
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					_{{stdout}}_
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Production mode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					_{{production:stdout}}_
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,36 @@
 | 
				
			||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const webpack = require("../../");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @type {webpack.Configuration} */
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						devtool: "source-map",
 | 
				
			||||||
 | 
						module: {
 | 
				
			||||||
 | 
							rules: [
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									test: /foo.txt/,
 | 
				
			||||||
 | 
									type: "asset/resource"
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									test: /bar.txt/,
 | 
				
			||||||
 | 
									use: require.resolve("file-loader")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						plugins: [
 | 
				
			||||||
 | 
							new webpack.ManifestPlugin({
 | 
				
			||||||
 | 
								filename: "manifest.json"
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
							new webpack.ManifestPlugin({
 | 
				
			||||||
 | 
								filename: "manifest.yml",
 | 
				
			||||||
 | 
								handle(manifest) {
 | 
				
			||||||
 | 
									let _manifest = "";
 | 
				
			||||||
 | 
									for (const key in manifest) {
 | 
				
			||||||
 | 
										if (key === "manifest.json") continue;
 | 
				
			||||||
 | 
										_manifest += `- ${key}: '${manifest[key]}'\n`;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return _manifest;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						]
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -355,6 +355,9 @@ module.exports = mergeExports(fn, {
 | 
				
			||||||
	get Stats() {
 | 
						get Stats() {
 | 
				
			||||||
		return require("./Stats");
 | 
							return require("./Stats");
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
						get ManifestPlugin() {
 | 
				
			||||||
 | 
							return require("./stats/ManifestPlugin");
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
	get Template() {
 | 
						get Template() {
 | 
				
			||||||
		return require("./Template");
 | 
							return require("./Template");
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,180 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
						MIT License http://www.opensource.org/licenses/mit-license.php
 | 
				
			||||||
 | 
						Author Haijie Xie @hai-x
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const path = require("path");
 | 
				
			||||||
 | 
					const { RawSource } = require("webpack-sources");
 | 
				
			||||||
 | 
					const Compilation = require("../Compilation");
 | 
				
			||||||
 | 
					const HotUpdateChunk = require("../HotUpdateChunk");
 | 
				
			||||||
 | 
					const createSchemaValidation = require("../util/create-schema-validation");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @typedef {import("../Compiler")} Compiler */
 | 
				
			||||||
 | 
					/** @typedef {import("..").StatsCompilation} StatsCompilation */
 | 
				
			||||||
 | 
					/** @typedef {import("../Chunk")} Chunk */
 | 
				
			||||||
 | 
					/** @typedef {import("../Compilation").Asset} Asset */
 | 
				
			||||||
 | 
					/** @typedef {import("../Module")} Module */
 | 
				
			||||||
 | 
					/** @typedef {import("../NormalModule")} NormalModule */
 | 
				
			||||||
 | 
					/** @typedef {import("../config/defaults").WebpackOptionsNormalizedWithDefaults} WebpackOptions */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @typedef {import("../../declarations/plugins/ManifestPlugin").ManifestPluginOptions} ManifestPluginOptions */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const PLUGIN_NAME = "ManifestPlugin";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const validate = createSchemaValidation(
 | 
				
			||||||
 | 
						require("../../schemas/plugins/ManifestPlugin.check"),
 | 
				
			||||||
 | 
						() => require("../../schemas/plugins/ManifestPlugin.json"),
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							name: "ManifestPlugin",
 | 
				
			||||||
 | 
							baseDataPath: "options"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @param {string} filename filename
 | 
				
			||||||
 | 
					 * @returns {string} extname
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const extname = (filename) => {
 | 
				
			||||||
 | 
						const replaced = filename.replace(/\?.*/, "");
 | 
				
			||||||
 | 
						const split = replaced.split(".");
 | 
				
			||||||
 | 
						const last = split.pop();
 | 
				
			||||||
 | 
						if (!last) return "";
 | 
				
			||||||
 | 
						return last && /^(gz|map)$/i.test(last) ? `${split.pop()}.${last}` : last;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ManifestPlugin {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param {ManifestPluginOptions} options options
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						constructor(options) {
 | 
				
			||||||
 | 
							validate(options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/** @type {Required<ManifestPluginOptions>} */
 | 
				
			||||||
 | 
							this.options = {
 | 
				
			||||||
 | 
								filename: "manifest.json",
 | 
				
			||||||
 | 
								handle: (manifest, _stats) => JSON.stringify(manifest, null, 2),
 | 
				
			||||||
 | 
								...options
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Apply the plugin
 | 
				
			||||||
 | 
						 * @param {Compiler} compiler the compiler instance
 | 
				
			||||||
 | 
						 * @returns {void}
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						apply(compiler) {
 | 
				
			||||||
 | 
							/** @type {WeakMap<Compilation, StatsCompilation>} */
 | 
				
			||||||
 | 
							const cachedStats = new WeakMap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
 | 
				
			||||||
 | 
								compilation.hooks.processAssets.tap(
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										name: PLUGIN_NAME,
 | 
				
			||||||
 | 
										stage: Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									() => {
 | 
				
			||||||
 | 
										let stats =
 | 
				
			||||||
 | 
											/** @type {StatsCompilation | undefined} */ cachedStats.get(
 | 
				
			||||||
 | 
												compilation
 | 
				
			||||||
 | 
											);
 | 
				
			||||||
 | 
										if (!stats) {
 | 
				
			||||||
 | 
											stats = compilation.getStats().toJson({
 | 
				
			||||||
 | 
												all: false,
 | 
				
			||||||
 | 
												assets: true,
 | 
				
			||||||
 | 
												cachedAssets: true,
 | 
				
			||||||
 | 
												assetsSpace: Infinity,
 | 
				
			||||||
 | 
												publicPath: true
 | 
				
			||||||
 | 
											});
 | 
				
			||||||
 | 
											cachedStats.set(compilation, stats);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										/** @type {Set<string>} */
 | 
				
			||||||
 | 
										const added = new Set();
 | 
				
			||||||
 | 
										/**
 | 
				
			||||||
 | 
										 * @type {{name: string, file: string}[]}
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
										const items = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										/**
 | 
				
			||||||
 | 
										 * @param {string} file file
 | 
				
			||||||
 | 
										 * @param {((file: string) => string)=} namer namer
 | 
				
			||||||
 | 
										 * @returns {void}
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
										const handleFile = (file, namer) => {
 | 
				
			||||||
 | 
											if (added.has(file)) return;
 | 
				
			||||||
 | 
											added.add(file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											let name = namer ? namer(file) : file;
 | 
				
			||||||
 | 
											const asset = compilation.getAsset(file);
 | 
				
			||||||
 | 
											if (asset && asset.info.sourceFilename) {
 | 
				
			||||||
 | 
												name = path.join(
 | 
				
			||||||
 | 
													path.dirname(file),
 | 
				
			||||||
 | 
													path.basename(asset.info.sourceFilename)
 | 
				
			||||||
 | 
												);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											items.push({ name, file });
 | 
				
			||||||
 | 
										};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										for (const chunk of compilation.chunks) {
 | 
				
			||||||
 | 
											if (chunk instanceof HotUpdateChunk) continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											const chunkName = chunk.name;
 | 
				
			||||||
 | 
											for (const auxiliaryFile of chunk.auxiliaryFiles) {
 | 
				
			||||||
 | 
												handleFile(auxiliaryFile, (file) => path.basename(file));
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											for (const file of chunk.files) {
 | 
				
			||||||
 | 
												handleFile(file, (file) => {
 | 
				
			||||||
 | 
													if (chunkName) return `${chunkName}.${extname(file)}`;
 | 
				
			||||||
 | 
													return file;
 | 
				
			||||||
 | 
												});
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if (stats.assets) {
 | 
				
			||||||
 | 
											for (const asset of stats.assets) {
 | 
				
			||||||
 | 
												if (asset.info.hotModuleReplacement) {
 | 
				
			||||||
 | 
													continue;
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
												handleFile(asset.name);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										/** @type {Record<string, string>} */
 | 
				
			||||||
 | 
										const manifest = {};
 | 
				
			||||||
 | 
										const hashDigestLength = compilation.outputOptions.hashDigestLength;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										/**
 | 
				
			||||||
 | 
										 * @param {string} name name
 | 
				
			||||||
 | 
										 * @returns {string} hash removed name
 | 
				
			||||||
 | 
										 */
 | 
				
			||||||
 | 
										const removeHash = (name) => {
 | 
				
			||||||
 | 
											// Handles hashes that match configured `hashDigestLength`
 | 
				
			||||||
 | 
											// i.e. index.XXXX.html -> index.html (html-webpack-plugin)
 | 
				
			||||||
 | 
											if (hashDigestLength <= 0) return name;
 | 
				
			||||||
 | 
											const reg = new RegExp(
 | 
				
			||||||
 | 
												`(\\.[a-f0-9]{${hashDigestLength}})(?=\\.)`,
 | 
				
			||||||
 | 
												"gi"
 | 
				
			||||||
 | 
											);
 | 
				
			||||||
 | 
											return name.replace(reg, "");
 | 
				
			||||||
 | 
										};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										for (const { name, file } of items) {
 | 
				
			||||||
 | 
											manifest[removeHash(name)] = stats.publicPath
 | 
				
			||||||
 | 
												? stats.publicPath +
 | 
				
			||||||
 | 
													(stats.publicPath.endsWith("/") ? `${file}` : `/${file}`)
 | 
				
			||||||
 | 
												: file;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										compilation.emitAsset(
 | 
				
			||||||
 | 
											this.options.filename,
 | 
				
			||||||
 | 
											new RawSource(this.options.handle(manifest, stats))
 | 
				
			||||||
 | 
										);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = ManifestPlugin;
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,7 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file was automatically generated.
 | 
				
			||||||
 | 
					 * DO NOT MODIFY BY HAND.
 | 
				
			||||||
 | 
					 * Run `yarn fix:special` to update
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					declare const check: (options: import("../../declarations/plugins/ManifestPlugin").ManifestPluginOptions) => boolean;
 | 
				
			||||||
 | 
					export = check;
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file was automatically generated.
 | 
				
			||||||
 | 
					 * DO NOT MODIFY BY HAND.
 | 
				
			||||||
 | 
					 * Run `yarn fix:special` to update
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const r=/^(?:[A-Za-z]:[\\/]|\\\\|\/)/;function e(t,{instancePath:a="",parentData:n,parentDataProperty:o,rootData:s=t}={}){if(!t||"object"!=typeof t||Array.isArray(t))return e.errors=[{params:{type:"object"}}],!1;{const a=0;for(const r in t)if("filename"!==r&&"handle"!==r)return e.errors=[{params:{additionalProperty:r}}],!1;if(0===a){if(void 0!==t.filename){let a=t.filename;const n=0;if(0===n){if("string"!=typeof a)return e.errors=[{params:{type:"string"}}],!1;if(a.includes("!")||!1!==r.test(a))return e.errors=[{params:{}}],!1;if(a.length<1)return e.errors=[{params:{}}],!1}var i=0===n}else i=!0;if(i)if(void 0!==t.handle){const r=0;if(!(t.handle instanceof Function))return e.errors=[{params:{}}],!1;i=0===r}else i=!0}}return e.errors=null,!0}module.exports=e,module.exports.default=e;
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  "title": "ManifestPluginOptions",
 | 
				
			||||||
 | 
					  "type": "object",
 | 
				
			||||||
 | 
					  "additionalProperties": false,
 | 
				
			||||||
 | 
					  "properties": {
 | 
				
			||||||
 | 
					    "filename": {
 | 
				
			||||||
 | 
					      "description": "Specifies the filename of the output file on disk. By default the plugin will emit `manifest.json` inside the 'output.path' directory.",
 | 
				
			||||||
 | 
					      "type": "string",
 | 
				
			||||||
 | 
					      "absolutePath": false,
 | 
				
			||||||
 | 
					      "minLength": 1
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "handle": {
 | 
				
			||||||
 | 
					      "description": "A custom Function to create the manifest.",
 | 
				
			||||||
 | 
					      "instanceof": "Function",
 | 
				
			||||||
 | 
					      "tsType": "((manifest: Record<string, string>, stats: import('../../lib/stats/DefaultStatsFactoryPlugin').StatsCompilation) => string)"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					file
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,30 @@
 | 
				
			||||||
 | 
					import fs from "fs";
 | 
				
			||||||
 | 
					import path from "path";
 | 
				
			||||||
 | 
					import url from "../../asset-modules/_images/file.png";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import(/* webpackChunkName: 'file' */ "./file.txt?foo");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					it("should emit manifest with expected entries and paths", () => {
 | 
				
			||||||
 | 
						expect(url).toEqual("/app/file-loader.png");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const manifest = JSON.parse(
 | 
				
			||||||
 | 
							fs.readFileSync(path.resolve(__dirname, "test.json"), "utf-8")
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const keys = Object.keys(manifest).sort();
 | 
				
			||||||
 | 
						expect(keys).toEqual(
 | 
				
			||||||
 | 
							[
 | 
				
			||||||
 | 
								"file.js",
 | 
				
			||||||
 | 
								"file.txt?foo",
 | 
				
			||||||
 | 
								"main.js",
 | 
				
			||||||
 | 
								"third.party.js",
 | 
				
			||||||
 | 
								"file.png"
 | 
				
			||||||
 | 
							].sort()
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expect(manifest["main.js"]).toMatch(/\/app\/bundle0\.js/);
 | 
				
			||||||
 | 
						expect(manifest["file.js"]).toMatch(/\/app\/file\.[a-f0-9]+\.js/);
 | 
				
			||||||
 | 
						expect(manifest["file.txt?foo"]).toMatch(/\/app\/file\.[a-f0-9]+\.txt\?foo/);
 | 
				
			||||||
 | 
						expect(manifest["third.party.js"]).toBe("/app/third.party.js");
 | 
				
			||||||
 | 
						expect(manifest["file.png"]).toBe("/app/file-loader.png");
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,7 @@
 | 
				
			||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = [
 | 
				
			||||||
 | 
						// each time returns different OriginalSource in webpack.config.js:33
 | 
				
			||||||
 | 
						// this prevents hit in inmemory cache
 | 
				
			||||||
 | 
						/^Pack got invalid because of write to: RealContentHashPlugin|analyse|third.party.js$/
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,61 @@
 | 
				
			||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { RawSource } = require("webpack-sources");
 | 
				
			||||||
 | 
					const webpack = require("../../../../");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @typedef {import("../../../../lib/Compiler")} Compiler */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CopyPlugin {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Apply the plugin
 | 
				
			||||||
 | 
						 * @param {Compiler} compiler the compiler instance
 | 
				
			||||||
 | 
						 * @returns {void}
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						apply(compiler) {
 | 
				
			||||||
 | 
							const hookOptions = {
 | 
				
			||||||
 | 
								name: "MockCopyPlugin",
 | 
				
			||||||
 | 
								stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							compiler.hooks.thisCompilation.tap(hookOptions, (compilation) => {
 | 
				
			||||||
 | 
								compilation.hooks.processAssets.tap(hookOptions, () => {
 | 
				
			||||||
 | 
									const output = "// some compilation result\n";
 | 
				
			||||||
 | 
									compilation.emitAsset("third.party.js", new RawSource(output));
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @type {import("../../../../").Configuration} */
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
						node: {
 | 
				
			||||||
 | 
							__dirname: false,
 | 
				
			||||||
 | 
							__filename: false
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						output: {
 | 
				
			||||||
 | 
							publicPath: "/app/",
 | 
				
			||||||
 | 
							chunkFilename: "[name].[contenthash].js",
 | 
				
			||||||
 | 
							assetModuleFilename: "[name].[contenthash][ext][query]"
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						plugins: [
 | 
				
			||||||
 | 
							new CopyPlugin(),
 | 
				
			||||||
 | 
							new webpack.ManifestPlugin({
 | 
				
			||||||
 | 
								filename: "test.json"
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
 | 
						module: {
 | 
				
			||||||
 | 
							rules: [
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									test: /\.txt$/,
 | 
				
			||||||
 | 
									type: "asset/resource"
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									test: /\.png$/,
 | 
				
			||||||
 | 
									loader: "file-loader",
 | 
				
			||||||
 | 
									options: {
 | 
				
			||||||
 | 
										name: "file-loader.[ext]"
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
"use strict";
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = [
 | 
					module.exports = [
 | 
				
			||||||
	// each time returns different OriginalSource in webpack.config.js:78
 | 
						// each time returns different OriginalSource in webpack.config.js:108
 | 
				
			||||||
	// this prevents hit in inmemory cache
 | 
						// this prevents hit in inmemory cache
 | 
				
			||||||
	/^Pack got invalid because of write to: RealContentHashPlugin|analyse|index\.html$/
 | 
						/^Pack got invalid because of write to: RealContentHashPlugin|analyse|index\.html$/
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9892,6 +9892,29 @@ declare interface MakeDirectoryOptions {
 | 
				
			||||||
	recursive?: boolean;
 | 
						recursive?: boolean;
 | 
				
			||||||
	mode?: string | number;
 | 
						mode?: string | number;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					declare class ManifestPlugin {
 | 
				
			||||||
 | 
						constructor(options: ManifestPluginOptions);
 | 
				
			||||||
 | 
						options: Required<ManifestPluginOptions>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Apply the plugin
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						apply(compiler: Compiler): void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					declare interface ManifestPluginOptions {
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Specifies the filename of the output file on disk. By default the plugin will emit `manifest.json` inside the 'output.path' directory.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						filename?: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * A custom Function to create the manifest.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						handle?: (
 | 
				
			||||||
 | 
							manifest: Record<string, string>,
 | 
				
			||||||
 | 
							stats: StatsCompilation
 | 
				
			||||||
 | 
						) => string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
declare interface MapOptions {
 | 
					declare interface MapOptions {
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * need columns?
 | 
						 * need columns?
 | 
				
			||||||
| 
						 | 
					@ -19271,6 +19294,7 @@ declare namespace exports {
 | 
				
			||||||
		EntryPlugin as SingleEntryPlugin,
 | 
							EntryPlugin as SingleEntryPlugin,
 | 
				
			||||||
		SourceMapDevToolPlugin,
 | 
							SourceMapDevToolPlugin,
 | 
				
			||||||
		Stats,
 | 
							Stats,
 | 
				
			||||||
 | 
							ManifestPlugin,
 | 
				
			||||||
		Template,
 | 
							Template,
 | 
				
			||||||
		WatchIgnorePlugin,
 | 
							WatchIgnorePlugin,
 | 
				
			||||||
		WebpackError,
 | 
							WebpackError,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue