|
| 1 | +/* |
| 2 | + MIT License http://www.opensource.org/licenses/mit-license.php |
| 3 | + Author Tobias Koppers @sokra |
| 4 | +
|
| 5 | + Forked to add support for `ignoreList`. |
| 6 | + Keep in sync with packages/next/webpack-plugins/eval-source-map-dev-tool-plugin.js |
| 7 | + */ |
| 8 | +// eslint-disable-next-line import/no-extraneous-dependencies -- this is a dev-only file |
| 9 | +const ConcatenatedModule = require('webpack/lib/optimize/ConcatenatedModule') |
| 10 | +// eslint-disable-next-line import/no-extraneous-dependencies -- this is a dev-only file |
| 11 | +const { makePathsAbsolute } = require('webpack/lib/util/identifier') |
| 12 | +// eslint-disable-next-line import/no-extraneous-dependencies -- this is a dev-only file |
| 13 | +const ModuleFilenameHelpers = require('webpack/lib/ModuleFilenameHelpers') |
| 14 | +// eslint-disable-next-line import/no-extraneous-dependencies -- this is a dev-only file |
| 15 | +const NormalModule = require('webpack/lib/NormalModule') |
| 16 | +// eslint-disable-next-line import/no-extraneous-dependencies -- this is a dev-only file |
| 17 | +const RuntimeGlobals = require('webpack/lib/RuntimeGlobals') |
| 18 | +// eslint-disable-next-line import/no-extraneous-dependencies -- this is a dev-only file |
| 19 | +const SourceMapDevToolModuleOptionsPlugin = require('webpack/lib/SourceMapDevToolModuleOptionsPlugin') |
| 20 | + |
| 21 | +const cache = new WeakMap() |
| 22 | +const devtoolWarningMessage = `/* |
| 23 | + * ATTENTION: An "eval-source-map" devtool has been used. |
| 24 | + * This devtool is neither made for production nor for readable output files. |
| 25 | + * It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools. |
| 26 | + * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) |
| 27 | + * or disable the default devtool with "devtool: false". |
| 28 | + * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). |
| 29 | + */ |
| 30 | +` |
| 31 | + |
| 32 | +// @ts-expect-error -- can't compare `string` with `number` in `version`Ï |
| 33 | + |
| 34 | +// Fork of webpack's EvalSourceMapDevToolPlugin with support for adding `ignoreList`. |
| 35 | +// https://github.com/webpack/webpack/blob/e237b580e2bda705c5ab39973f786f7c5a7026bc/lib/EvalSourceMapDevToolPlugin.js#L37 |
| 36 | +module.exports = class EvalSourceMapDevToolPlugin { |
| 37 | + sourceMapComment |
| 38 | + moduleFilenameTemplate |
| 39 | + namespace |
| 40 | + options |
| 41 | + shouldIgnorePath |
| 42 | + |
| 43 | + /** |
| 44 | + * @param {SourceMapDevToolPluginOptions|string} inputOptions Options object |
| 45 | + */ |
| 46 | + constructor(inputOptions) { |
| 47 | + let options |
| 48 | + if (typeof inputOptions === 'string') { |
| 49 | + options = { |
| 50 | + append: inputOptions, |
| 51 | + } |
| 52 | + } else { |
| 53 | + options = inputOptions |
| 54 | + } |
| 55 | + this.sourceMapComment = |
| 56 | + options.append && typeof options.append !== 'function' |
| 57 | + ? options.append |
| 58 | + : '//# sourceURL=[module]\n//# sourceMappingURL=[url]' |
| 59 | + this.moduleFilenameTemplate = |
| 60 | + options.moduleFilenameTemplate || |
| 61 | + 'webpack://[namespace]/[resource-path]?[hash]' |
| 62 | + this.namespace = options.namespace || '' |
| 63 | + this.options = options |
| 64 | + |
| 65 | + // fork |
| 66 | + this.shouldIgnorePath = options.shouldIgnorePath ?? (() => false) |
| 67 | + } |
| 68 | + |
| 69 | + /** |
| 70 | + * Apply the plugin |
| 71 | + * @param compiler the compiler instance |
| 72 | + */ |
| 73 | + apply(compiler) { |
| 74 | + const options = this.options |
| 75 | + compiler.hooks.compilation.tap( |
| 76 | + 'NextJSEvalSourceMapDevToolPlugin', |
| 77 | + (compilation) => { |
| 78 | + const { JavascriptModulesPlugin } = compiler.webpack.javascript |
| 79 | + const { RawSource, ConcatSource } = compiler.webpack.sources |
| 80 | + const devtoolWarning = new RawSource(devtoolWarningMessage) |
| 81 | + const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation) |
| 82 | + new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation) |
| 83 | + const matchModule = ModuleFilenameHelpers.matchObject.bind( |
| 84 | + ModuleFilenameHelpers, |
| 85 | + options |
| 86 | + ) |
| 87 | + hooks.renderModuleContent.tap( |
| 88 | + 'NextJSEvalSourceMapDevToolPlugin', |
| 89 | + (source, m, { chunk, runtimeTemplate, chunkGraph }) => { |
| 90 | + const cachedSource = cache.get(source) |
| 91 | + if (cachedSource !== undefined) { |
| 92 | + return cachedSource |
| 93 | + } |
| 94 | + const result = (r) => { |
| 95 | + cache.set(source, r) |
| 96 | + return r |
| 97 | + } |
| 98 | + if (m instanceof NormalModule) { |
| 99 | + const module = m |
| 100 | + if (!matchModule(module.resource)) { |
| 101 | + return result(source) |
| 102 | + } |
| 103 | + } else if (m instanceof ConcatenatedModule) { |
| 104 | + const concatModule = m |
| 105 | + if (concatModule.rootModule instanceof NormalModule) { |
| 106 | + const module = concatModule.rootModule |
| 107 | + if (!matchModule(module.resource)) { |
| 108 | + return result(source) |
| 109 | + } |
| 110 | + } else { |
| 111 | + return result(source) |
| 112 | + } |
| 113 | + } else { |
| 114 | + return result(source) |
| 115 | + } |
| 116 | + const namespace = compilation.getPath(this.namespace, { |
| 117 | + chunk, |
| 118 | + }) |
| 119 | + let sourceMap |
| 120 | + let content |
| 121 | + if (source.sourceAndMap) { |
| 122 | + const sourceAndMap = source.sourceAndMap(options) |
| 123 | + sourceMap = sourceAndMap.map |
| 124 | + content = sourceAndMap.source |
| 125 | + } else { |
| 126 | + sourceMap = source.map(options) |
| 127 | + content = source.source() |
| 128 | + } |
| 129 | + if (!sourceMap) { |
| 130 | + return result(source) |
| 131 | + } |
| 132 | + |
| 133 | + // Clone (flat) the sourcemap to ensure that the mutations below do not persist. |
| 134 | + sourceMap = { |
| 135 | + ...sourceMap, |
| 136 | + } |
| 137 | + const context = compiler.options.context |
| 138 | + const root = compiler.root |
| 139 | + const modules = sourceMap.sources.map((sourceMapSource) => { |
| 140 | + if (!sourceMapSource.startsWith('webpack://')) |
| 141 | + return sourceMapSource |
| 142 | + sourceMapSource = makePathsAbsolute( |
| 143 | + context, |
| 144 | + sourceMapSource.slice(10), |
| 145 | + root |
| 146 | + ) |
| 147 | + const module = compilation.findModule(sourceMapSource) |
| 148 | + return module || sourceMapSource |
| 149 | + }) |
| 150 | + let moduleFilenames = modules.map((module) => |
| 151 | + ModuleFilenameHelpers.createFilename( |
| 152 | + module, |
| 153 | + { |
| 154 | + moduleFilenameTemplate: this.moduleFilenameTemplate, |
| 155 | + namespace, |
| 156 | + }, |
| 157 | + { |
| 158 | + requestShortener: runtimeTemplate.requestShortener, |
| 159 | + chunkGraph, |
| 160 | + hashFunction: compilation.outputOptions.hashFunction, |
| 161 | + } |
| 162 | + ) |
| 163 | + ) |
| 164 | + moduleFilenames = ModuleFilenameHelpers.replaceDuplicates( |
| 165 | + moduleFilenames, |
| 166 | + (filename, _i, n) => { |
| 167 | + for (let j = 0; j < n; j++) filename += '*' |
| 168 | + return filename |
| 169 | + } |
| 170 | + ) |
| 171 | + sourceMap.sources = moduleFilenames |
| 172 | + sourceMap.ignoreList = [] |
| 173 | + for (let index = 0; index < moduleFilenames.length; index++) { |
| 174 | + if (this.shouldIgnorePath(moduleFilenames[index])) { |
| 175 | + sourceMap.ignoreList.push(index) |
| 176 | + } |
| 177 | + } |
| 178 | + if (options.noSources) { |
| 179 | + sourceMap.sourcesContent = undefined |
| 180 | + } |
| 181 | + sourceMap.sourceRoot = options.sourceRoot || '' |
| 182 | + const moduleId = /** @type {ModuleId} */ chunkGraph.getModuleId(m) |
| 183 | + if (moduleId) { |
| 184 | + sourceMap.file = |
| 185 | + typeof moduleId === 'number' ? `${moduleId}.js` : moduleId |
| 186 | + } |
| 187 | + 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 |
| 188 | + |
| 189 | + return result( |
| 190 | + new RawSource( |
| 191 | + `eval(${compilation.outputOptions.trustedTypes ? `${RuntimeGlobals.createScript}(${JSON.stringify(content + footer)})` : JSON.stringify(content + footer)});` |
| 192 | + ) |
| 193 | + ) |
| 194 | + } |
| 195 | + ) |
| 196 | + hooks.inlineInRuntimeBailout.tap( |
| 197 | + 'EvalDevToolModulePlugin', |
| 198 | + () => 'the eval-source-map devtool is used.' |
| 199 | + ) |
| 200 | + hooks.render.tap( |
| 201 | + 'EvalSourceMapDevToolPlugin', |
| 202 | + (source) => new ConcatSource(devtoolWarning, source) |
| 203 | + ) |
| 204 | + hooks.chunkHash.tap('EvalSourceMapDevToolPlugin', (_chunk, hash) => { |
| 205 | + hash.update('EvalSourceMapDevToolPlugin') |
| 206 | + hash.update('2') |
| 207 | + }) |
| 208 | + if (compilation.outputOptions.trustedTypes) { |
| 209 | + compilation.hooks.additionalModuleRuntimeRequirements.tap( |
| 210 | + 'EvalSourceMapDevToolPlugin', |
| 211 | + (_module, set, _context) => { |
| 212 | + set.add(RuntimeGlobals.createScript) |
| 213 | + } |
| 214 | + ) |
| 215 | + } |
| 216 | + } |
| 217 | + ) |
| 218 | + } |
| 219 | +} |
0 commit comments