UNPKG

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