Skip to content

Commit

Permalink
ported code to webpack 4
Browse files Browse the repository at this point in the history
  • Loading branch information
malectro committed Mar 26, 2018
1 parent d21232c commit a9f27d3
Showing 1 changed file with 90 additions and 57 deletions.
147 changes: 90 additions & 57 deletions lib/ChunkManifestPlugin.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,99 @@
var RawSource = require("webpack-core/lib/RawSource");
const pluginName = 'ChunkManifestPlugin';

function ChunkManifestPlugin(options) {
options = options || {};
this.manifestFilename = options.filename || "manifest.json";
this.manifestVariable = options.manifestVariable || "webpackManifest";
this.inlineManifest = options.inlineManifest || false;
}
module.exports = ChunkManifestPlugin;
class ChunkManifestPlugin {
constructor(options) {
this.options = {
filename: 'manifest.json',
manifestVariable: 'webpackManifest',
inlineManifest: false,
...options,
};
}

apply(compiler) {
const chunkManifestFilename = '__CHUNK_MANIFEST__';
let chunkManifest;
let oldChunkFilename;

compiler.hooks.thisCompilation.tap(pluginName, compilation => {
const {mainTemplate} = compilation;

mainTemplate.hooks.requireEnsure.tap(
pluginName,
(source, chunk, hash) => {
const {outputOptions} = mainTemplate;
const filename =
outputOptions.chunkFilename || outputOptions.filename;

ChunkManifestPlugin.prototype.constructor = ChunkManifestPlugin;
ChunkManifestPlugin.prototype.apply = function(compiler) {
var manifestFilename = this.manifestFilename;
var manifestVariable = this.manifestVariable;
var inlineManifest = this.inlineManifest;
var oldChunkFilename;
var chunkManifest;

compiler.plugin("this-compilation", function(compilation) {
var mainTemplate = compilation.mainTemplate;
mainTemplate.plugin("require-ensure", function(_, chunk, hash) {
var filename = this.outputOptions.chunkFilename || this.outputOptions.filename;

if (filename) {
chunkManifest = [chunk].reduce(function registerChunk(manifest, c) {
if(c.id in manifest) return manifest;
var hasRuntime = typeof c.hasRuntime === 'function' ? c.hasRuntime() : c.entry;
if(hasRuntime) {
manifest[c.id] = undefined;
} else {
manifest[c.id] = mainTemplate.applyPluginsWaterfall("asset-path", filename, {
hash: hash,
chunk: c
});
if (filename) {
const registerChunk = (manifest, chunk) => {
if (chunk.id in manifest) {
return manifest;
}

if (chunk.hasRuntime()) {
manifest[chunk.id] = undefined;
} else {
manifest[chunk.id] = mainTemplate.getAssetPath(filename, {
hash,
chunk,
});
}

return Array.from(chunk.getAllAsyncChunks()).reduce(
registerChunk,
manifest,
);
};
chunkManifest = registerChunk({}, chunk);

oldChunkFilename = outputOptions.chunkFilename;
outputOptions.chunkFilename = chunkManifestFilename;

const source = JSON.stringify(chunkManifest, null, true);
compilation.assets[this.options.filename] = {
source: () => source,
size: () => source.length,
};
chunk.files.push(this.options.filename);
}
return c.chunks.reduce(registerChunk, manifest);
}, {});
oldChunkFilename = this.outputOptions.chunkFilename;
this.outputOptions.chunkFilename = "__CHUNK_MANIFEST__";
// mark as asset for emitting
compilation.assets[manifestFilename] = new RawSource(JSON.stringify(chunkManifest));
chunk.files.push(manifestFilename);
}

return _;
return source;
},
);
});
});

compiler.plugin("compilation", function(compilation) {
compilation.mainTemplate.plugin("require-ensure", function(_, chunk, hash, chunkIdVar) {
if (oldChunkFilename) {
this.outputOptions.chunkFilename = oldChunkFilename;
}
compiler.hooks.compilation.tap(pluginName, compilation => {
const {mainTemplate} = compilation;

mainTemplate.hooks.requireEnsure.tap(
pluginName,
(source, chunk, hash, chunkId) => {
if (oldChunkFilename) {
mainTemplate.outputOptions.chunkFilename = oldChunkFilename;

return source.replace(
`"${chunkManifestFilename}"`,
`window['${this.options.manifestVariable}']['${chunkId}']`,
);
}
},
);

if (this.options.inlineManifest) {
const {htmlWebpackPluginBeforeHtmlGeneration} = compilation.hooks;

return _.replace("\"__CHUNK_MANIFEST__\"",
"window[\"" + manifestVariable + "\"][" + chunkIdVar + "]");
if (htmlWebpackPluginBeforeHtmlGeneration) {
const {manifestVariable} = this.options;

htmlWebpackPluginBeforeHtmlGeneration.tap(pluginName, data => {
const manifestHtml = `<script>window.${manifestVariable}=${JSON.stringify(chunkManifest)}</script>`;
return data.assets[manifestVariable] = manifestHtml;
});
}
}
});
}
}

if (inlineManifest){
compilation.plugin("html-webpack-plugin-before-html-generation", function (data, callback) {
var manifestHtml = "<script>window." + manifestVariable + "=" + JSON.stringify(chunkManifest) + "</script>";
callback(null, data.assets[manifestVariable] = manifestHtml);
});
}
});
};
module.exports = ChunkManifestPlugin;

3 comments on commit a9f27d3

@mojoaxel
Copy link

Choose a reason for hiding this comment

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

@malectro Are you interested in creating a pull request for this? See soundcloud#55 (comment)

@malectro
Copy link
Owner Author

@malectro malectro commented on a9f27d3 Apr 17, 2018

Choose a reason for hiding this comment

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

yeah, i'm down. i wasn't totally sure how to test it because i didn't use any of the htmlWebpack or inline manifest stuff in my implementation.

Edit: looks like i do have a PR? soundcloud#56

@mojoaxel
Copy link

Choose a reason for hiding this comment

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

Edit: looks like i do have a PR? soundcloud#56

Sorry! I didn't see it. Thanks!

Please sign in to comment.