You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

EvalSourceMapDevToolModuleTemplatePlugin.js 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const { RawSource } = require("webpack-sources");
  7. const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
  8. const cache = new WeakMap();
  9. class EvalSourceMapDevToolModuleTemplatePlugin {
  10. constructor(compilation, options) {
  11. this.compilation = compilation;
  12. this.sourceMapComment =
  13. options.append || "//# sourceURL=[module]\n//# sourceMappingURL=[url]";
  14. this.moduleFilenameTemplate =
  15. options.moduleFilenameTemplate ||
  16. "webpack://[namespace]/[resource-path]?[hash]";
  17. this.namespace = options.namespace || "";
  18. this.options = options;
  19. }
  20. apply(moduleTemplate) {
  21. const self = this;
  22. const options = this.options;
  23. const matchModule = ModuleFilenameHelpers.matchObject.bind(
  24. ModuleFilenameHelpers,
  25. options
  26. );
  27. moduleTemplate.hooks.module.tap(
  28. "EvalSourceMapDevToolModuleTemplatePlugin",
  29. (source, module) => {
  30. const cachedSource = cache.get(source);
  31. if (cachedSource !== undefined) {
  32. return cachedSource;
  33. }
  34. if (!matchModule(module.resource)) {
  35. return source;
  36. }
  37. /** @type {{ [key: string]: TODO; }} */
  38. let sourceMap;
  39. let content;
  40. if (source.sourceAndMap) {
  41. const sourceAndMap = source.sourceAndMap(options);
  42. sourceMap = sourceAndMap.map;
  43. content = sourceAndMap.source;
  44. } else {
  45. sourceMap = source.map(options);
  46. content = source.source();
  47. }
  48. if (!sourceMap) {
  49. return source;
  50. }
  51. // Clone (flat) the sourcemap to ensure that the mutations below do not persist.
  52. sourceMap = Object.keys(sourceMap).reduce((obj, key) => {
  53. obj[key] = sourceMap[key];
  54. return obj;
  55. }, {});
  56. const modules = sourceMap.sources.map(source => {
  57. const module = self.compilation.findModule(source);
  58. return module || source;
  59. });
  60. let moduleFilenames = modules.map(module => {
  61. return ModuleFilenameHelpers.createFilename(
  62. module,
  63. {
  64. moduleFilenameTemplate: self.moduleFilenameTemplate,
  65. namespace: self.namespace
  66. },
  67. moduleTemplate.runtimeTemplate.requestShortener
  68. );
  69. });
  70. moduleFilenames = ModuleFilenameHelpers.replaceDuplicates(
  71. moduleFilenames,
  72. (filename, i, n) => {
  73. for (let j = 0; j < n; j++) filename += "*";
  74. return filename;
  75. }
  76. );
  77. sourceMap.sources = moduleFilenames;
  78. sourceMap.sourceRoot = options.sourceRoot || "";
  79. sourceMap.file = `${module.id}.js`;
  80. const footer =
  81. self.sourceMapComment.replace(
  82. /\[url\]/g,
  83. `data:application/json;charset=utf-8;base64,${Buffer.from(
  84. JSON.stringify(sourceMap),
  85. "utf8"
  86. ).toString("base64")}`
  87. ) + `\n//# sourceURL=webpack-internal:///${module.id}\n`; // workaround for chrome bug
  88. const evalSource = new RawSource(
  89. `eval(${JSON.stringify(content + footer)});`
  90. );
  91. cache.set(source, evalSource);
  92. return evalSource;
  93. }
  94. );
  95. moduleTemplate.hooks.hash.tap(
  96. "EvalSourceMapDevToolModuleTemplatePlugin",
  97. hash => {
  98. hash.update("eval-source-map");
  99. hash.update("2");
  100. }
  101. );
  102. }
  103. }
  104. module.exports = EvalSourceMapDevToolModuleTemplatePlugin;