AutoPublicPathRuntimeModule.js 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. */
  4. "use strict";
  5. const RuntimeGlobals = require("../RuntimeGlobals");
  6. const RuntimeModule = require("../RuntimeModule");
  7. const Template = require("../Template");
  8. const JavascriptModulesPlugin = require("../javascript/JavascriptModulesPlugin");
  9. const { getUndoPath } = require("../util/identifier");
  10. /** @typedef {import("../Compilation")} Compilation */
  11. class AutoPublicPathRuntimeModule extends RuntimeModule {
  12. constructor() {
  13. super("publicPath", RuntimeModule.STAGE_BASIC);
  14. }
  15. /**
  16. * @returns {string | null} runtime code
  17. */
  18. generate() {
  19. const compilation = /** @type {Compilation} */ (this.compilation);
  20. const { scriptType, importMetaName, path } = compilation.outputOptions;
  21. const chunkName = compilation.getPath(
  22. JavascriptModulesPlugin.getChunkFilenameTemplate(
  23. this.chunk,
  24. compilation.outputOptions
  25. ),
  26. {
  27. chunk: this.chunk,
  28. contentHashType: "javascript"
  29. }
  30. );
  31. const undoPath = getUndoPath(
  32. chunkName,
  33. /** @type {string} */ (path),
  34. false
  35. );
  36. return Template.asString([
  37. "var scriptUrl;",
  38. scriptType === "module"
  39. ? `if (typeof ${importMetaName}.url === "string") scriptUrl = ${importMetaName}.url`
  40. : Template.asString([
  41. `if (${RuntimeGlobals.global}.importScripts) scriptUrl = ${RuntimeGlobals.global}.location + "";`,
  42. `var document = ${RuntimeGlobals.global}.document;`,
  43. "if (!scriptUrl && document) {",
  44. Template.indent([
  45. `if (document.currentScript)`,
  46. Template.indent(`scriptUrl = document.currentScript.src;`),
  47. "if (!scriptUrl) {",
  48. Template.indent([
  49. 'var scripts = document.getElementsByTagName("script");',
  50. "if(scripts.length) {",
  51. Template.indent([
  52. "var i = scripts.length - 1;",
  53. "while (i > -1 && (!scriptUrl || !/^http(s?):/.test(scriptUrl))) scriptUrl = scripts[i--].src;"
  54. ]),
  55. "}"
  56. ]),
  57. "}"
  58. ]),
  59. "}"
  60. ]),
  61. "// When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration",
  62. '// or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic.',
  63. 'if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser");',
  64. 'scriptUrl = scriptUrl.replace(/#.*$/, "").replace(/\\?.*$/, "").replace(/\\/[^\\/]+$/, "/");',
  65. !undoPath
  66. ? `${RuntimeGlobals.publicPath} = scriptUrl;`
  67. : `${RuntimeGlobals.publicPath} = scriptUrl + ${JSON.stringify(
  68. undoPath
  69. )};`
  70. ]);
  71. }
  72. }
  73. module.exports = AutoPublicPathRuntimeModule;