UNPKG

webpack

Version:

Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.

190 lines (175 loc) 6.33 kB
/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const { ConcatSource, RawSource } = require("webpack-sources"); const ModuleFilenameHelpers = require("./ModuleFilenameHelpers"); const NormalModule = require("./NormalModule"); const SourceMapDevToolModuleOptionsPlugin = require("./SourceMapDevToolModuleOptionsPlugin"); const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin"); const ConcatenatedModule = require("./optimize/ConcatenatedModule"); const { makePathsAbsolute } = require("./util/identifier"); /** @typedef {import("webpack-sources").Source} Source */ /** @typedef {import("../declarations/WebpackOptions").DevTool} DevToolOptions */ /** @typedef {import("../declarations/plugins/SourceMapDevToolPlugin").SourceMapDevToolPluginOptions} SourceMapDevToolPluginOptions */ /** @typedef {import("./Compiler")} Compiler */ /** @type {WeakMap<Source, Source>} */ const cache = new WeakMap(); const devtoolWarning = new RawSource(`/* * ATTENTION: An "eval-source-map" devtool has been used. * This devtool is neither made for production nor for readable output files. * It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools. * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) * or disable the default devtool with "devtool: false". * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). */ `); class EvalSourceMapDevToolPlugin { /** * @param {SourceMapDevToolPluginOptions|string} inputOptions Options object */ constructor(inputOptions) { /** @type {SourceMapDevToolPluginOptions} */ let options; if (typeof inputOptions === "string") { options = { append: inputOptions }; } else { options = inputOptions; } this.sourceMapComment = options.append || "//# sourceURL=[module]\n//# sourceMappingURL=[url]"; this.moduleFilenameTemplate = options.moduleFilenameTemplate || "webpack://[namespace]/[resource-path]?[hash]"; this.namespace = options.namespace || ""; this.options = options; } /** * Apply the plugin * @param {Compiler} compiler the compiler instance * @returns {void} */ apply(compiler) { const options = this.options; compiler.hooks.compilation.tap( "EvalSourceMapDevToolPlugin", compilation => { const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation); new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation); const matchModule = ModuleFilenameHelpers.matchObject.bind( ModuleFilenameHelpers, options ); hooks.renderModuleContent.tap( "EvalSourceMapDevToolPlugin", (source, m, { runtimeTemplate, chunkGraph }) => { const cachedSource = cache.get(source); if (cachedSource !== undefined) { return cachedSource; } const result = r => { cache.set(source, r); return r; }; if (m instanceof NormalModule) { const module = /** @type {NormalModule} */ (m); if (!matchModule(module.resource)) { return result(source); } } else if (m instanceof ConcatenatedModule) { const concatModule = /** @type {ConcatenatedModule} */ (m); if (concatModule.rootModule instanceof NormalModule) { const module = /** @type {NormalModule} */ ( concatModule.rootModule ); if (!matchModule(module.resource)) { return result(source); } } else { return result(source); } } else { return result(source); } /** @type {{ [key: string]: TODO; }} */ let sourceMap; let content; if (source.sourceAndMap) { const sourceAndMap = source.sourceAndMap(options); sourceMap = sourceAndMap.map; content = sourceAndMap.source; } else { sourceMap = source.map(options); content = source.source(); } if (!sourceMap) { return result(source); } // Clone (flat) the sourcemap to ensure that the mutations below do not persist. sourceMap = { ...sourceMap }; const context = compiler.options.context; const root = compiler.root; const modules = sourceMap.sources.map(source => { if (!source.startsWith("webpack://")) return source; source = makePathsAbsolute(context, source.slice(10), root); const module = compilation.findModule(source); return module || source; }); let moduleFilenames = modules.map(module => { return ModuleFilenameHelpers.createFilename( module, { moduleFilenameTemplate: this.moduleFilenameTemplate, namespace: this.namespace }, { requestShortener: runtimeTemplate.requestShortener, chunkGraph, hashFunction: compilation.outputOptions.hashFunction } ); }); moduleFilenames = ModuleFilenameHelpers.replaceDuplicates( moduleFilenames, (filename, i, n) => { for (let j = 0; j < n; j++) filename += "*"; return filename; } ); sourceMap.sources = moduleFilenames; sourceMap.sourceRoot = options.sourceRoot || ""; const moduleId = chunkGraph.getModuleId(m); sourceMap.file = `${moduleId}.js`; const footer = this.sourceMapComment.replace( /\[url\]/g, `data:application/json;charset=utf-8;base64,${Buffer.from( JSON.stringify(sourceMap), "utf8" ).toString("base64")}` ) + `\n//# sourceURL=webpack-internal:///${moduleId}\n`; // workaround for chrome bug return result( new RawSource(`eval(${JSON.stringify(content + footer)});`) ); } ); hooks.inlineInRuntimeBailout.tap( "EvalDevToolModulePlugin", () => "the eval-source-map devtool is used." ); hooks.render.tap( "EvalSourceMapDevToolPlugin", source => new ConcatSource(devtoolWarning, source) ); hooks.chunkHash.tap("EvalSourceMapDevToolPlugin", (chunk, hash) => { hash.update("EvalSourceMapDevToolPlugin"); hash.update("2"); }); } ); } } module.exports = EvalSourceMapDevToolPlugin;