"use strict"; function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } 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 _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } var path = require("path"); var fse = require("fs-extra"); var createHash = require("webpack/lib/util/createHash"); var fs = require("fs"); var ExternalModuleFactoryPlugin = require("./ExternalModuleFactory"); // const FunctionModuleTemplatePlugin = require("webpack/lib/FunctionModuleTemplatePlugin"); var _require = require("./utils"), mergeDeep = _require.mergeDeep; var _require2 = require("./requireExtentions"), addInterleaveExtension = _require2.addInterleaveExtension, addInterleaveRequire = _require2.addInterleaveRequire; var _require3 = require("./beforeStartup"), addWebpackRegister = _require3.addWebpackRegister; var _require4 = require("./chunkSplitting"), interleaveStyleConfig = _require4.interleaveStyleConfig, interleaveStyleJsConfig = _require4.interleaveStyleJsConfig, interleaveConfig = _require4.interleaveConfig, hasExternalizedModuleViaJson = _require4.hasExternalizedModuleViaJson; var _require5 = require("./localVars"), addLocalVars = _require5.addLocalVars; var _require6 = require("./optimizeChunk"), wrapChunks = _require6.wrapChunks; var emitCountMap = new Map(); function getFileType(str) { var split = str.replace(/\?.*/, "").split("."); return split.pop(); } var URLImportPlugin = /*#__PURE__*/ function () { function URLImportPlugin(opts) { _classCallCheck(this, URLImportPlugin); var debug = (typeof v8debug === "undefined" ? "undefined" : _typeof(v8debug)) === "object" || /--debug|--inspect/.test(process.execArgv.join(" ")); if (!opts.manifestName) { throw new Error("URLImportPlugin: You MUST specify a manifestName in your options. Something unique. Like {manifestName: my-special-build}"); } this.opts = _objectSpread({ publicPath: null, debug: debug || false, testPath: "src", basePath: "", manifestName: "unknown-project", fileName: "importManifest.js", writeToFileEmit: false, seed: null, filter: null, hashDigest: "base64", hashDigestLength: 5, context: null, hashFunction: "md4" }, opts || {}); } _createClass(URLImportPlugin, [{ key: "apply", value: function apply(compiler) { var _options$optimization, _options$optimization2, _this = this, _options$optimization3; if (this.opts.debug) {} var options = compiler === null || compiler === void 0 ? void 0 : compiler.options; if (options.externals) { throw new Error("URLImportPlugin: Externals must be applied via the plugin, not via webpack config object. Please see useExternals on the plugin documentation"); } // add to the existing webpack config // adding a new splitChunks cache group called interleave var chunkSplitting = (options === null || options === void 0 ? void 0 : (_options$optimization = options.optimization) === null || _options$optimization === void 0 ? void 0 : (_options$optimization2 = _options$optimization.splitChunks) === null || _options$optimization2 === void 0 ? void 0 : _options$optimization2.cacheGroups) || {}; chunkSplitting.stylejs = interleaveStyleJsConfig(this.opts); chunkSplitting.style = interleaveStyleConfig(this.opts); // interleaveConfig figures out if a file meets the paramaters for interleaving chunkSplitting.interleave = interleaveConfig(this.opts); if (options.mode === "production") { chunkSplitting.vendors = { name: "".concat(this.opts.manifestName, "-vendors"), test: /node_modules/, priority: -10, enforce: true, maxSize: 50000 }; Object.assign(chunkSplitting["default"], { maxSize: 50000 }); } Object.assign(options.optimization || {}, { namedChunks: true, // dont rename exports when hoisting and tree shaking providedExports: false }); // likely will be refactored or removed, used for entryManifest.js to map chunks (this is V1 where its outside the runtime still) if (this.opts.debug) {} // merge my added splitChunks config into the webpack config object passed in Object.assign(options.optimization.splitChunks, { chunks: "all" }); mergeDeep(options, { optimization: { splitChunks: { chunks: "all", cacheGroups: chunkSplitting } } }); Object.keys(chunkSplitting).forEach(function (key) { var _chunkSplitting$key; if (key === "interleave") { return; } chunkSplitting[key].automaticNamePrefix = "".concat(_this.opts.manifestName, "~").concat((chunkSplitting === null || chunkSplitting === void 0 ? void 0 : (_chunkSplitting$key = chunkSplitting[key]) === null || _chunkSplitting$key === void 0 ? void 0 : _chunkSplitting$key.automaticNamePrefix) || ""); }); Object.assign(options.optimization, { // node debugger breaks with TerserPlugin minimizer: this.opts.debug ? [] : options.optimization.minimizer, splitChunks: ((_options$optimization3 = options.optimization) === null || _options$optimization3 === void 0 ? void 0 : _options$optimization3.splitChunks) || {} }); // forcefully mutate it Object.assign(options.optimization.splitChunks, { chunks: "all", cacheGroups: chunkSplitting }); if (this.opts.debug) {} // eslint-disable-next-line no-unused-vars compiler.hooks.thisCompilation.tap("URLImportPlugin", function (compilation) {// TODO: throw warning when changing module ID type // if (options.ignoreOrder) { // compilation.warnings.push( // new Error( // `chunk ${chunk.name || chunk.id} [${pluginName}]\n` // + 'Conflicting order between:\n' // + ` * ${fallbackModule.readableIdentifier( // requestShortener, // )}\n` // + `${bestMatchDeps // .map(m => ` * ${m.readableIdentifier(requestShortener)}`) // .join('\n')}`, // ), // ); // } }); var moduleAssets = {}; var outputFolder = compiler.options.output.path; var outputFile = path.resolve(outputFolder, this.opts.fileName); var outputName = path.relative(outputFolder, outputFile); var moduleAsset = function moduleAsset(_ref, file) { var userRequest = _ref.userRequest; if (userRequest) { moduleAssets[file] = path.join(path.dirname(file), path.basename(userRequest)); } }; var emit = function emit(compilation, compileCallback) { var 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(); if (_this.opts.debug) {} var files = compilation.chunks.reduce(function (f, chunk) { return chunk.files.reduce(function (fx, filePath) { var name = chunk.id ? chunk.id : null; if (name) { name = "".concat(name, ".").concat(getFileType(filePath)); } else { // For nameless chunks, just map the files directly. name = filePath; } return fx.concat({ path: filePath, chunk: chunk, name: name, isChunk: true, isAsset: false, isModuleAsset: false }); }, f); }, []); // module assets don't show up in assetsByChunkName. // we're getting them this way; files = stats.assets.reduce(function (fx, asset) { var name = moduleAssets[asset.name]; if (name) { return fx.concat({ path: asset.name, name: name }); } var isEntryAsset = asset.chunks.length > 0; if (isEntryAsset) { return fx; } return fx.concat({ path: asset.name, name: asset.name }); }, files); files = files.filter(function (file) { // Don't add hot updates to manifest var isUpdateChunk = file.path.includes("hot-update"); // Don't add manifest from another instance var isManifest = emitCountMap.get(path.join(outputFolder, file.name)) !== undefined; return !isUpdateChunk && !isManifest; }); if (_this.opts.debug) {} // 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) { return _objectSpread({}, file, { name: _this.opts.basePath + file.name }); }); } if (publicPath) { // 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) { return _objectSpread({}, file, { path: publicPath + file.path }); }); } files = files.map(function (file) { return _objectSpread({}, file, { name: file.name.replace(/\\/g, "/"), path: file.path.replace(/\\/g, "/") }); }); if (_this.opts.filter) { files = files.filter(_this.opts.filter); } if (_this.opts.debug) {} var manifest = files.reduce(function (m, file) { return _objectSpread({}, m, _defineProperty({}, file.name, { path: file.path })); }, seed); if (_this.opts.debug) {} var isLastEmit = emitCount === 0; if (isLastEmit) { var cleanedManifest = Object.entries(manifest).reduce(function (acc, _ref2) { var _asset$path; var _ref3 = _slicedToArray(_ref2, 2), key = _ref3[0], asset = _ref3[1]; if (!(asset === null || asset === void 0 ? void 0 : (_asset$path = asset.path) === null || _asset$path === void 0 ? void 0 : _asset$path.includes(".map"))) { return Object.assign(acc, _defineProperty({}, key, asset)); } return acc; }, {}); var serialize = function serialize(manifest) { return "if(!window.entryManifest) {window.entryManifest = {}}; window.entryManifest[\"".concat(_this.opts.manifestName, "\"] = ").concat(JSON.stringify(manifest)); }; var output = serialize(cleanedManifest); if (_this.opts.debug) {} // eslint-disable-next-line no-param-reassign compilation.assets[outputName] = { source: function source() { return output; }, size: function size() { return output.length; } }; if (_this.opts.writeToFileEmit) { fse.outputFileSync(outputFile, output); } } if (compiler.hooks) { compiler.hooks.webpackURLImportPluginAfterEmit.call(manifest); } else { compilation.applyPluginsAsync("webpack-manifest-plugin-after-emit", manifest, compileCallback); } }; function beforeRun(comp, callback) { var emitCount = emitCountMap.get(outputFile) || 0; emitCountMap.set(outputFile, emitCount + 1); if (callback) { callback(); } } if (compiler.hooks) { var _require7 = require("tapable"), SyncWaterfallHook = _require7.SyncWaterfallHook; var pluginOptions = { name: "URLImportPlugin", stage: Infinity }; // eslint-disable-next-line no-param-reassign compiler.hooks.webpackURLImportPluginAfterEmit = new SyncWaterfallHook(["manifest"]); compiler.hooks.compile.tap("ExternalsPlugin", function (_ref4) { var normalModuleFactory = _ref4.normalModuleFactory; new ExternalModuleFactoryPlugin(options.output.libraryTarget, _this.opts.useExternals).apply(normalModuleFactory); }); compiler.hooks.compilation.tap("URLImportPlugin", function (compilation) { var mainTemplate = compilation.mainTemplate; // Add another webpack__require method to the webpack runtime // this new method will allow a interleaved component to be required and automatically download its dependencies // it returns a promise so the actual interleaved module is not executed until any missing dependencies are loaded mainTemplate.hooks.requireExtensions.tap("URLImportPlugin", function (source) { return [addInterleaveExtension, addInterleaveRequire].reduce(function (sourceCode, extension) { return extension(sourceCode, mainTemplate.requireFn, _this.opts); }, source); }); // TODO add an option for this if (_this.afterOptimizations) { // before chunk files are optimized compilation.hooks.beforeOptimizeChunkAssets.tap("URLImportPlugin", function (chunks) { // access all chunks webpack created, then add some code to each chunk file, which is run when a chunk is // loaded on a page as