Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add reference to webpack.Compilation to generate #216

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ module.exports = {
Type: `String`<br>
Default: `manifest.json`

By default the plugin will emit `manifest.json` to your output directory. Can override with an absolute path.
By default the plugin will emit `manifest.json` to your output directory. Can override with an absolute path.

### `options.publicPath`

Expand Down Expand Up @@ -108,10 +108,12 @@ Sort files before they are passed to `generate`. [FileDescriptor typings](#filed

### `options.generate`

Type: `Function(Object, FileDescriptor, string[]): Object`<br>
Default: `(seed, files, entrypoints) => files.reduce((manifest, {name, path}) => ({...manifest, [name]: path}), seed)`
Type: `Function(Object, FileDescriptor, string[], webpack.Compilation): Object`<br>
Default: `(seed, files, entrypoints, compilation) => files.reduce((manifest, {name, path}) => ({...manifest, [name]: path}), seed)`

Create the manifest. It can return anything as long as it's serialisable by `JSON.stringify`. [FileDescriptor typings](#filedescriptor)
Create the manifest. It can return anything as long as it's serialisable by `JSON.stringify`. [FileDescriptor typings](#filedescriptor).

The `compilation` object is a reference to the [Webpack Compilation](https://webpack.js.org/api/compilation-object/) object and allows you to extend this package's functionalitiy with for example Integrity checking. See [`./examples/integrity-manifest.js`](./examples/integrity-manifest.js) for an example.

### `options.serialize`

Expand Down
36 changes: 36 additions & 0 deletions examples/integrity-manifest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const ManifestPlugin = require('webpack-manifest-plugin');
const crypto = require('crypto');

/**
* This example returns a manifest object containing
* each path with a integrity hash:
*
* {
* "main.bd17d3636cb.js": "sha256-4a97d363df66cd8a4f4bd16cb80026bcf50fd9233761de21c34a5b55293345d2"
* }
*
* It can be used in combination with for example the
* webpack-subresource-integrity package.
*/
module.exports = {
plugins: [
new ManifestPlugin({
generate: (seed, files, entrypoints, compilation) => {
return files.reduce((manifest, { path, name }) => {
const compilationAsset = compilation.assets[name];
// Use 'integrity' as set by webpack-subresource-integrity or
// generate a new hash
const integrity = compilationAsset ? compilationAsset.integrity || createIntegrityHash(compilationAsset.source()) : null;
return { ...manifest, [path]: integrity };
}, seed);
}
}),
]
};

function createIntegrityHash(content, algorithm = 'sha256') {
const hash = crypto.createHash(algorithm)
.update(content, 'utf-8')
.digest('hex');
return algorithm + '-' + hash;
}
34 changes: 17 additions & 17 deletions lib/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function ManifestPlugin(opts) {
map: null,
generate: null,
sort: null,
serialize: function(manifest) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should revert changes in this file

serialize: function (manifest) {
return JSON.stringify(manifest, null, 2);
},
}, opts || {});
Expand All @@ -41,7 +41,7 @@ ManifestPlugin.getCompilerHooks = (compiler) => {
return hooks;
}

ManifestPlugin.prototype.getFileType = function(str) {
ManifestPlugin.prototype.getFileType = function (str) {
str = str.replace(/\?.*/, '');
var split = str.split('.');
var ext = split.pop();
Expand All @@ -51,7 +51,7 @@ ManifestPlugin.prototype.getFileType = function(str) {
return ext;
};

ManifestPlugin.prototype.apply = function(compiler) {
ManifestPlugin.prototype.apply = function (compiler) {
var moduleAssets = {};

var outputFolder = compiler.options.output.path;
Expand All @@ -68,23 +68,23 @@ ManifestPlugin.prototype.apply = function(compiler) {
};


var emit = function(compilation, compileCallback) {
var emit = function (compilation, compileCallback) {
const emitCount = emitCountMap.get(outputFile) - 1
emitCountMap.set(outputFile, emitCount);

var seed = this.opts.seed || {};

var publicPath = this.opts.publicPath != null ? this.opts.publicPath : compilation.options.output.publicPath;
var stats = compilation.getStats().toJson({
// Disable data generation of everything we don't use
all: false,
// Add asset Information
assets: true,
// Show cached assets (setting this to `false` only shows emitted files)
cachedAssets: true,
// Disable data generation of everything we don't use
all: false,
// Add asset Information
assets: true,
// Show cached assets (setting this to `false` only shows emitted files)
cachedAssets: true,
});

var files = compilation.chunks.reduce(function(files, chunk) {
var files = compilation.chunks.reduce(function (files, chunk) {
return chunk.files.reduce(function (files, path) {
var name = chunk.name ? chunk.name : null;

Expand Down Expand Up @@ -152,7 +152,7 @@ ManifestPlugin.prototype.apply = function(compiler) {
// Append optional basepath onto all references.
// This allows output path to be reflected in the manifest.
if (this.opts.basePath) {
files = files.map(function(file) {
files = files.map(function (file) {
file.name = this.opts.basePath + file.name;
return file;
}.bind(this));
Expand All @@ -162,7 +162,7 @@ ManifestPlugin.prototype.apply = function(compiler) {
// Similar to basePath but only affects the value (similar to how
// output.publicPath turns require('foo/bar') into '/public/foo/bar', see
// https://github.com/webpack/docs/wiki/configuration#outputpublicpath
files = files.map(function(file) {
files = files.map(function (file) {
file.path = publicPath + file.path;
return file;
}.bind(this));
Expand Down Expand Up @@ -195,7 +195,7 @@ ManifestPlugin.prototype.apply = function(compiler) {
(e, [name, entrypoint]) => Object.assign(e, { [name]: entrypoint.getFiles() }),
{}
);
manifest = this.opts.generate(seed, files, entrypoints);
manifest = this.opts.generate(seed, files, entrypoints, compilation);
} else {
manifest = files.reduce(function (manifest, file) {
manifest[file.name] = file.path;
Expand All @@ -208,10 +208,10 @@ ManifestPlugin.prototype.apply = function(compiler) {
var output = this.opts.serialize(manifest);

compilation.assets[outputName] = {
source: function() {
source: function () {
return output;
},
size: function() {
size: function () {
return output.length;
}
};
Expand All @@ -228,7 +228,7 @@ ManifestPlugin.prototype.apply = function(compiler) {
}
}.bind(this);

function beforeRun (compiler, callback) {
function beforeRun(compiler, callback) {
let emitCount = emitCountMap.get(outputFile) || 0;
emitCountMap.set(outputFile, emitCount + 1);

Expand Down