next
Version:
The React Framework
152 lines (150 loc) • 8.06 kB
JavaScript
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
Forked to add support for `ignoreList`.
Keep in sync with packages/next/webpack-plugins/eval-source-map-dev-tool-plugin.js
*/ import { ConcatenatedModule, makePathsAbsolute, ModuleFilenameHelpers, NormalModule, RuntimeGlobals, SourceMapDevToolModuleOptionsPlugin } from 'next/dist/compiled/webpack/webpack';
const cache = new WeakMap();
const devtoolWarningMessage = `/*
* 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/).
*/
`;
// Fork of webpack's EvalSourceMapDevToolPlugin with support for adding `ignoreList`.
// https://github.com/webpack/webpack/blob/e237b580e2bda705c5ab39973f786f7c5a7026bc/lib/EvalSourceMapDevToolPlugin.js#L37
export default class EvalSourceMapDevToolPlugin {
/**
* @param {SourceMapDevToolPluginOptions|string} inputOptions Options object
*/ constructor(inputOptions){
let options;
if (typeof inputOptions === 'string') {
options = {
append: inputOptions
};
} else {
options = inputOptions;
}
this.sourceMapComment = options.append && typeof options.append !== 'function' ? options.append : '//# sourceURL=[module]\n//# sourceMappingURL=[url]';
this.moduleFilenameTemplate = options.moduleFilenameTemplate || 'webpack://[namespace]/[resource-path]?[hash]';
this.namespace = options.namespace || '';
this.options = options;
// fork
this.shouldIgnorePath = options.shouldIgnorePath ?? (()=>false);
}
/**
* Apply the plugin
* @param compiler the compiler instance
*/ apply(compiler) {
const options = this.options;
compiler.hooks.compilation.tap('NextJSEvalSourceMapDevToolPlugin', (compilation)=>{
const { JavascriptModulesPlugin } = compiler.webpack.javascript;
const { RawSource, ConcatSource } = compiler.webpack.sources;
const devtoolWarning = new RawSource(devtoolWarningMessage);
const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation);
new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation);
const matchModule = ModuleFilenameHelpers.matchObject.bind(ModuleFilenameHelpers, options);
hooks.renderModuleContent.tap('NextJSEvalSourceMapDevToolPlugin', (source, m, { chunk, 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 = m;
if (!matchModule(module.resource)) {
return result(source);
}
} else if (m instanceof ConcatenatedModule) {
const concatModule = m;
if (concatModule.rootModule instanceof NormalModule) {
const module = concatModule.rootModule;
if (!matchModule(module.resource)) {
return result(source);
}
} else {
return result(source);
}
} else {
return result(source);
}
const namespace = compilation.getPath(this.namespace, {
chunk
});
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((sourceMapSource)=>{
if (!sourceMapSource.startsWith('webpack://')) return sourceMapSource;
sourceMapSource = makePathsAbsolute(context, sourceMapSource.slice(10), root);
const module = compilation.findModule(sourceMapSource);
return module || sourceMapSource;
});
let moduleFilenames = modules.map((module)=>ModuleFilenameHelpers.createFilename(module, {
moduleFilenameTemplate: this.moduleFilenameTemplate,
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.ignoreList = [];
for(let index = 0; index < moduleFilenames.length; index++){
if (this.shouldIgnorePath(moduleFilenames[index])) {
sourceMap.ignoreList.push(index);
}
}
if (options.noSources) {
sourceMap.sourcesContent = undefined;
}
sourceMap.sourceRoot = options.sourceRoot || '';
const moduleId = /** @type {ModuleId} */ chunkGraph.getModuleId(m);
if (moduleId) {
sourceMap.file = typeof moduleId === 'number' ? `${moduleId}.js` : moduleId;
}
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(${compilation.outputOptions.trustedTypes ? `${RuntimeGlobals.createScript}(${JSON.stringify(content + footer)})` : 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');
});
if (compilation.outputOptions.trustedTypes) {
compilation.hooks.additionalModuleRuntimeRequirements.tap('EvalSourceMapDevToolPlugin', (_module, set, _context)=>{
set.add(RuntimeGlobals.createScript);
});
}
});
}
}
//# sourceMappingURL=eval-source-map-dev-tool-plugin.js.map