1 | # Webpack Assets Manifest
|
2 |
|
3 | [![Build Status](https://github.com/webdeveric/webpack-assets-manifest/workflows/Node.js%20CI/badge.svg)](https://github.com/webdeveric/webpack-assets-manifest/actions)
|
4 | [![codecov](https://codecov.io/gh/webdeveric/webpack-assets-manifest/branch/master/graph/badge.svg)](https://codecov.io/gh/webdeveric/webpack-assets-manifest)
|
5 | [![dependencies Status](https://david-dm.org/webdeveric/webpack-assets-manifest/status.svg)](https://david-dm.org/webdeveric/webpack-assets-manifest)
|
6 | [![devDependencies Status](https://david-dm.org/webdeveric/webpack-assets-manifest/dev-status.svg)](https://david-dm.org/webdeveric/webpack-assets-manifest?type=dev)
|
7 |
|
8 | This webpack plugin will generate a JSON file that matches the original filename with the hashed version.
|
9 |
|
10 | ## Installation
|
11 |
|
12 | - Version 4 works with webpack 4.40+ (webpack 4 branch only)
|
13 | - Version 3.1 works with webpack 4.4+.
|
14 | - Version 2 works with webpack 4+.
|
15 |
|
16 | ```shell
|
17 | npm install webpack-assets-manifest --save-dev
|
18 | ```
|
19 |
|
20 | If you're using webpack 3 or below, you'll need to install version 1.
|
21 |
|
22 | ```shell
|
23 | npm install webpack-assets-manifest@1 --save-dev
|
24 | ```
|
25 |
|
26 | ## New in version 4
|
27 |
|
28 | * Requires Node 10+.
|
29 | * Compatible with webpack 4 only (4.40+ required).
|
30 | * Added options: [`enabled`](#enabled), [`entrypointsUseAssets`](#entrypointsUseAssets), [`contextRelativeKeys`](#contextRelativeKeys).
|
31 | * Updated [`writeToDisk`](#writeToDisk) option to default to `auto`.
|
32 | * Use lock files for various operations.
|
33 | * `done` hook is now an `AsyncSeriesHook`.
|
34 |
|
35 | ## Usage
|
36 |
|
37 | In your webpack config, require the plugin then add an instance to the `plugins` array.
|
38 |
|
39 | ```js
|
40 | const path = require('path');
|
41 | const WebpackAssetsManifest = require('webpack-assets-manifest');
|
42 |
|
43 | module.exports = {
|
44 | entry: {
|
45 | // Your entry points
|
46 | },
|
47 | output: {
|
48 | path: path.join( __dirname, 'dist' ),
|
49 | filename: '[name]-[hash].js',
|
50 | chunkFilename: '[id]-[chunkhash].js',
|
51 | },
|
52 | module: {
|
53 | // Your loader rules go here.
|
54 | },
|
55 | plugins: [
|
56 | new WebpackAssetsManifest({
|
57 | // Options go here
|
58 | }),
|
59 | ],
|
60 | };
|
61 | ```
|
62 |
|
63 | ## Sample output
|
64 |
|
65 | ```json
|
66 | {
|
67 | "main.js": "main-9c68d5e8de1b810a80e4.js",
|
68 | "main.css": "main-9c68d5e8de1b810a80e4.css",
|
69 | "images/logo.svg": "images/logo-b111da4f34cefce092b965ebc1078ee3.svg"
|
70 | }
|
71 | ```
|
72 |
|
73 | ---
|
74 |
|
75 | ## Options ([read the schema](src/options-schema.json))
|
76 |
|
77 | ### `enabled`
|
78 |
|
79 | Type: `boolean`
|
80 |
|
81 | Default: `true`
|
82 |
|
83 | Is the plugin enabled?
|
84 |
|
85 | ### `output`
|
86 |
|
87 | Type: `string`
|
88 |
|
89 | Default: `manifest.json`
|
90 |
|
91 | This is where to save the manifest file relative to your webpack `output.path`.
|
92 |
|
93 | ### `assets`
|
94 |
|
95 | Type: `object`
|
96 |
|
97 | Default: `{}`
|
98 |
|
99 | Data is stored in this object.
|
100 |
|
101 | #### Sharing data
|
102 |
|
103 | You can share data between instances by passing in your own object in the `assets` option.
|
104 |
|
105 | This is useful in [multi-compiler mode](https://github.com/webpack/webpack/tree/master/examples/multi-compiler).
|
106 |
|
107 | ```js
|
108 | const data = Object.create(null);
|
109 |
|
110 | const manifest1 = new WebpackAssetsManifest({
|
111 | assets: data,
|
112 | });
|
113 |
|
114 | const manifest2 = new WebpackAssetsManifest({
|
115 | assets: data,
|
116 | });
|
117 | ```
|
118 |
|
119 | ### `contextRelativeKeys`
|
120 |
|
121 | Type: `boolean`
|
122 |
|
123 | Default: `false`
|
124 |
|
125 | Keys are relative to the compiler context.
|
126 |
|
127 | ### `space`
|
128 |
|
129 | Type: `int`
|
130 |
|
131 | Default: `2`
|
132 |
|
133 | Number of spaces to use for pretty printing.
|
134 |
|
135 | ### `replacer`
|
136 |
|
137 | Type: `null`, `function`, or `array`
|
138 |
|
139 | Default: `null`
|
140 |
|
141 | [Replacer reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter)
|
142 |
|
143 | You'll probably want to use the `transform` hook instead.
|
144 |
|
145 | ### `fileExtRegex`
|
146 |
|
147 | Type: `regex`
|
148 |
|
149 | Default: `/\.\w{2,4}\.(?:map|gz)$|\.\w+$/i`
|
150 |
|
151 | This is the regular expression used to find file extensions. You'll probably never need to change this.
|
152 |
|
153 | ### `writeToDisk`
|
154 |
|
155 | Type: `boolean`, `string`
|
156 |
|
157 | Default: `'auto'`
|
158 |
|
159 | Write the manifest to disk using `fs`.
|
160 |
|
161 | :warning: If you're using another language for your site and you're using `webpack-dev-server` to process your assets during development,
|
162 | you should set `writeToDisk: true` and provide an absolute path in `output` so the manifest file is actually written to disk and not kept only in memory.
|
163 |
|
164 | ### `sortManifest`
|
165 |
|
166 | Type: `boolean`, `function`
|
167 |
|
168 | Default: `true`
|
169 |
|
170 | The manifest is sorted alphabetically by default. You can turn off sorting by setting `sortManifest: false`.
|
171 |
|
172 | If you want more control over how the manifest is sorted, you can provide your own
|
173 | [comparison function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#Parameters).
|
174 | See the [sorted](examples/sorted.js) example.
|
175 |
|
176 | ```js
|
177 | new WebpackAssetsManifest({
|
178 | sortManifest(a, b) {
|
179 | // Return -1, 0, or 1
|
180 | }
|
181 | });
|
182 | ```
|
183 |
|
184 | ### `merge`
|
185 |
|
186 | Type: `boolean`, `string`
|
187 |
|
188 | Default: `false`
|
189 |
|
190 | If the `output` file already exists and you'd like to add to it, use `merge: true`.
|
191 | The default behavior is to use the existing keys/values without modification.
|
192 |
|
193 | ```js
|
194 | new WebpackAssetsManifest({
|
195 | output: '/path/to/manifest.json',
|
196 | merge: true
|
197 | });
|
198 | ```
|
199 |
|
200 | If you need to customize during merge, use `merge: 'customize'`.
|
201 |
|
202 | If you want to know if `customize` was called when merging with an existing manifest, you can check `manifest.isMerging`.
|
203 |
|
204 | ```js
|
205 | new WebpackAssetsManifest({
|
206 | merge: 'customize',
|
207 | customize(entry, original, manifest, asset) {
|
208 | if ( manifest.isMerging ) {
|
209 | // Do something
|
210 | }
|
211 | },
|
212 | }),
|
213 | ```
|
214 |
|
215 | ### `publicPath`
|
216 |
|
217 | Type: `string`, `function`, `boolean`,
|
218 |
|
219 | Default: `null`
|
220 |
|
221 | When using `publicPath: true`, your webpack config `output.publicPath` will be used as the value prefix.
|
222 |
|
223 | ```js
|
224 | const manifest = new WebpackAssetsManifest({
|
225 | publicPath: true,
|
226 | });
|
227 | ```
|
228 |
|
229 | When using a string, it will be the value prefix. One common use is to prefix your CDN URL.
|
230 |
|
231 | ```js
|
232 | const manifest = new WebpackAssetsManifest({
|
233 | publicPath: '//cdn.example.com',
|
234 | });
|
235 | ```
|
236 |
|
237 | If you'd like to have more control, use a function. See the [custom CDN](examples/custom-cdn.js) example.
|
238 |
|
239 | ```js
|
240 | const manifest = new WebpackAssetsManifest({
|
241 | publicPath(filename, manifest)
|
242 | {
|
243 | // customize filename here
|
244 | return filename;
|
245 | }
|
246 | });
|
247 | ```
|
248 |
|
249 | ### `entrypoints`
|
250 |
|
251 | Type: `boolean`
|
252 |
|
253 | Default: `false`
|
254 |
|
255 | Include `compilation.entrypoints` in the manifest file.
|
256 |
|
257 | ### `entrypointsKey`
|
258 |
|
259 | Type: `string`, `boolean`
|
260 |
|
261 | Default: `entrypoints`
|
262 |
|
263 | If this is set to `false`, the `entrypoints` will be added to the root of the manifest.
|
264 |
|
265 | ### `entrypointsUseAssets`
|
266 |
|
267 | Type: `boolean`
|
268 |
|
269 | Default: `false`
|
270 |
|
271 | Entrypoint data should use the value from `assets`, which means the values could be customized and not just a `string` file path.
|
272 | This new option defaults to `false` so the new behavior is opt-in.
|
273 |
|
274 | ### `integrity`
|
275 |
|
276 | Type: `boolean`
|
277 |
|
278 | Default: `false`
|
279 |
|
280 | Include the [subresource integrity hash](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity).
|
281 |
|
282 | ### `integrityHashes`
|
283 |
|
284 | Type: `array`
|
285 |
|
286 | Default: `[ 'sha256', 'sha384', 'sha512' ]`
|
287 |
|
288 | Hash algorithms to use when generating SRI. For browsers, the currently the allowed integrity hashes are `sha256`, `sha384`, and `sha512`.
|
289 |
|
290 | Other hash algorithms can be used if your target environment is not a browser.
|
291 | If you were to create a tool to audit your S3 buckets for
|
292 | [data integrity](https://aws.amazon.com/premiumsupport/knowledge-center/data-integrity-s3/),
|
293 | you could use something like this [example](examples/aws-s3-data-integrity.js) to record the `md5` hashes.
|
294 |
|
295 | ### `integrityPropertyName`
|
296 |
|
297 | Type: `string`
|
298 |
|
299 | Default: `integrity`
|
300 |
|
301 | This is the property that will be set on each entry in `compilation.assets`, which will then be available during `customize`.
|
302 | It is customizable so that you can have multiple instances of this plugin and not have them overwrite the `currentAsset.integrity` property.
|
303 |
|
304 | You'll probably only need to change this if you're using multiple instances of this plugin to create different manifests.
|
305 |
|
306 | ### `apply`
|
307 |
|
308 | Type: `function`
|
309 |
|
310 | Default: `null`
|
311 |
|
312 | Callback to run after setup is complete.
|
313 |
|
314 | ### `customize`
|
315 |
|
316 | Type: `function`
|
317 |
|
318 | Default: `null`
|
319 |
|
320 | Callback to customize each entry in the manifest.
|
321 |
|
322 | ### `transform`
|
323 |
|
324 | Type: `function`
|
325 |
|
326 | Default: `null`
|
327 |
|
328 | Callback to transform the entire manifest.
|
329 |
|
330 | ### `done`
|
331 |
|
332 | Type: `function`
|
333 |
|
334 | Default: `null`
|
335 |
|
336 | Callback to run after the compilation is done and the manifest has been written.
|
337 |
|
338 | ---
|
339 |
|
340 | ### Hooks
|
341 |
|
342 | This plugin is using hooks from [Tapable](https://github.com/webpack/tapable/).
|
343 |
|
344 | The `apply`, `customize`, `transform`, and `done` options are automatically tapped into the appropriate hook.
|
345 |
|
346 | | Name | Type | Callback signature |
|
347 | | ---- | ---- | --------- |
|
348 | | `apply` | `SyncHook` | `function(manifest){}` |
|
349 | | `customize` | `SyncWaterfallHook` | `function(entry, original, manifest, asset){}` |
|
350 | | `transform` | `SyncWaterfallHook` | `function(assets, manifest){}` |
|
351 | | `done` | `AsyncSeriesHook` | `async function(manifest, stats){}` |
|
352 | | `options` | `SyncWaterfallHook` | `function(options){}` |
|
353 | | `afterOptions` | `SyncHook` | `function(options){}` |
|
354 |
|
355 | #### Tapping into hooks
|
356 |
|
357 | Tap into a hook by calling the `tap` method on the hook as shown below.
|
358 |
|
359 | If you want more control over exactly what gets added to your manifest, then use the `customize` and `transform` hooks.
|
360 | See the [customized](examples/customized.js) and [transformed](examples/transformed.js) examples.
|
361 |
|
362 | ```js
|
363 | const manifest = new WebpackAssetsManifest();
|
364 |
|
365 | manifest.hooks.apply.tap('YourPluginName', function(manifest) {
|
366 | // Do something here
|
367 | manifest.set('some-key', 'some-value');
|
368 | });
|
369 |
|
370 | manifest.hooks.customize.tap('YourPluginName', function(entry, original, manifest, asset) {
|
371 | // customize entry here
|
372 | return entry;
|
373 | });
|
374 |
|
375 | manifest.hooks.transform.tap('YourPluginName', function(assets, manifest) {
|
376 | // customize assets here
|
377 | return assets;
|
378 | });
|
379 |
|
380 | manifest.hooks.options.tap('YourPluginName', function(options) {
|
381 | // customize options here
|
382 | return options;
|
383 | });
|
384 |
|
385 | manifest.hooks.done.tap('YourPluginName', function(manifest, stats) {
|
386 | console.log(`The manifest has been written to ${manifest.getOutputPath()}`);
|
387 | console.log(`${manifest}`);
|
388 | });
|
389 |
|
390 | manifest.hooks.done.tapPromise('YourPluginName', async (manifest, stats) => {
|
391 | await yourAsyncOperation();
|
392 | });
|
393 | ```
|
394 |
|
395 | These hooks can also be set by passing them in the constructor options.
|
396 |
|
397 | ```js
|
398 | new WebpackAssetsManifest({
|
399 | done(manifest, stats) {
|
400 | console.log(`The manifest has been written to ${manifest.getOutputPath()}`);
|
401 | console.log(`${manifest}`);
|
402 | }
|
403 | });
|
404 | ```
|
405 |
|
406 | ## Manifest methods
|
407 |
|
408 | If the manifest instance is passed to a hook, you can use the following methods to manage what goes into the manifest.
|
409 |
|
410 | - `has(key)`
|
411 | - `get(key)`
|
412 | - `set(key, value)`
|
413 | - `setRaw(key, value)`
|
414 | - `delete(key)`
|
415 |
|
416 | If you want to write the manifest to another location, you can use `writeTo(destination)`.
|
417 |
|
418 | ```js
|
419 | new WebpackAssetsManifest({
|
420 | async done(manifest) {
|
421 | await manifest.writeTo('/some/other/path/assets-manifest.json');
|
422 | }
|
423 | });
|
424 | ```
|
425 |
|