From a9f27d34544bc03cdbbee1f2a566cb79f1d30b9f Mon Sep 17 00:00:00 2001 From: Kyle Warren Date: Mon, 26 Mar 2018 12:32:07 -0700 Subject: [PATCH] ported code to webpack 4 --- lib/ChunkManifestPlugin.js | 147 +++++++++++++++++++++++-------------- 1 file changed, 90 insertions(+), 57 deletions(-) diff --git a/lib/ChunkManifestPlugin.js b/lib/ChunkManifestPlugin.js index 4da72d0..8d625d6 100644 --- a/lib/ChunkManifestPlugin.js +++ b/lib/ChunkManifestPlugin.js @@ -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 = ``; + return data.assets[manifestVariable] = manifestHtml; + }); + } + } }); + } +} - if (inlineManifest){ - compilation.plugin("html-webpack-plugin-before-html-generation", function (data, callback) { - var manifestHtml = ""; - callback(null, data.assets[manifestVariable] = manifestHtml); - }); - } - }); -}; +module.exports = ChunkManifestPlugin;