"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.wrapChunks = wrapChunks; function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } var ModuleFilenameHelpers = require("webpack/lib/ModuleFilenameHelpers"); var _require = require("webpack-sources"), ConcatSource = _require.ConcatSource; var mem = require("mem"); function wrapFile(compilation, fileName, allModulesNeeded, chunkKeys) { // create a stringified array var outputOptions = compilation.output; var pushArguments = JSON.stringify([// pass the source compilation hash to figure out if a chunk is being required by its own build - if so, dont register anything { hash: compilation.hash, publicPath: (outputOptions === null || outputOptions === void 0 ? void 0 : outputOptions.publicPath) || "/" }, // array of keys to look up values in the allModulesNeeded hashmap chunkKeys, allModulesNeeded]); // add chunk registration code that will push all chunk requirements into webpack // eslint-disable-next-line no-param-reassign compilation.assets[fileName] = new ConcatSource(String("(window[\"webpackRegister\"] = window[\"webpackRegister\"] || []).push(".concat(pushArguments, ");\n")), compilation.assets[fileName]); } var loopFiles = mem(function (files) { return files.filter(function (file) { return file.includes(".css"); }); }); // eslint-disable-next-line import/prefer-default-export function wrapChunks(compilation, chunks) { // create a maps var map = { ignoredChunk: new Set() }; var orgs = {}; // loop over each chunk chunks.forEach(function (chunk) { // map weak maps and weak sets for better organization & perf // console.group(group) // check if this chunk is an entrypoint or has the webpack runtime // if it does, dont bother mapping registration data or include them in any other chunks registration maps if (chunk.hasEntryModule() || chunk.hasRuntime()) { map.ignoredChunk.add(chunk.id); } else {} // dont run if this has already been done on the chunk if (!chunk.rendered) { return; } // get all the modules in a chunk and loop over them chunk.getModules().forEach(function (module) { // add the chunk ID as a key and create an empty array if one isnt there already if (!(map[chunk.id] instanceof Object)) { map[chunk.id] = { js: [], css: [] }; } // push each module in a chunk into its array within the map if (module.id) map[chunk.id].js.push("".concat(module.id)); map[chunk.id].css = [].concat(_toConsumableArray(map[chunk.id].css), _toConsumableArray(loopFiles(chunk.files))); // check the reason a chunk exists, this is an array which returns any and all modules that depend on the current module module.reasons.forEach(function (reason) { if (reason.module) { // if theres a module, loop over the chunks this module is in reason.module.chunksIterable.forEach(function (reasonChunk) { // add the chunkID of where this module exists if (!orgs[reasonChunk.id]) orgs[reasonChunk.id] = { js: new Set(), css: new Set() }; orgs[reasonChunk.id].css = new Set([].concat(_toConsumableArray(orgs[reasonChunk.id].css), _toConsumableArray(loopFiles(reasonChunk.files)))); // console.log("reasonChunk", reasonChunk); // orgs[chunk.id].add(`${module.id}-${module.rawRequest}`); // add the chunkID that depends on this module if (chunk.id) orgs[reasonChunk.id].js.add(chunk.id); }); } }); }); // loop over everything and add the all other chunks a chunk depends on. // this creates a map telling us what a chunk needs and where to find it // chunks usually wont contain ALL the dependencies they need, so i need to make sure that i record what files contain dependencies // this chunk needs in order to be executed successfully Object.keys(orgs).forEach(function (key) { orgs[key].js.forEach(function (subSet) { if (orgs[subSet]) { var _orgs$subSet$js; (_orgs$subSet$js = orgs[subSet].js)["delete"].apply(_orgs$subSet$js, _toConsumableArray(map.ignoredChunk)); // dont walk entry or runtime chunks if (!map.ignoredChunk.has(subSet)) { var _orgs$key$js, _orgs$key$css; if (orgs[subSet].js.size) (_orgs$key$js = orgs[key].js).add.apply(_orgs$key$js, _toConsumableArray(orgs[subSet].js)); if (orgs[subSet].css.size) (_orgs$key$css = orgs[key].css).add.apply(_orgs$key$css, _toConsumableArray(orgs[subSet].css)); } } }); }); }); // to ensure the chunk maps are complete, i run another loop over the chunks - the previous loop creates a complete map // this loop uses the completed map to write the chunk registration data into each chunk file chunks.forEach(function (chunk) { if (!chunk.rendered || map.ignoredChunk.has(chunk.id)) { return; } // loop over all files that make up this chunk // eslint-disable-next-line no-restricted-syntax var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = chunk.files[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var fileName = _step.value; // check that its a javascript file (might be an image, html, css) if (ModuleFilenameHelpers.matchObject({}, fileName) && fileName.indexOf(".js") !== -1) { var _orgs$chunk$id; // get all the chunksID's the current chunk might need var AllChunksNeeded = Array.from((orgs === null || orgs === void 0 ? void 0 : (_orgs$chunk$id = orgs[chunk.id]) === null || _orgs$chunk$id === void 0 ? void 0 : _orgs$chunk$id.js) || new Set()); // create the final map which contains an array of chunkID as well as a object of chunk of what each chunk needs var AllModulesNeeded = AllChunksNeeded.reduce(function (allDependencies, dependentChunk) { return _objectSpread({}, allDependencies, _defineProperty({}, dependentChunk, { js: _toConsumableArray(new Set(map[dependentChunk].js)), css: _toConsumableArray(new Set(map[dependentChunk].css)) })); }, {}); // now that we have maps of what the current file being iterated needs, write additional code to the file wrapFile(compilation, fileName, AllModulesNeeded, AllChunksNeeded); } } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator["return"] != null) { _iterator["return"](); } } finally { if (_didIteratorError) { throw _iteratorError; } } } }); }