AutoPublicPathRuntimeModule.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  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. class AutoPublicPathRuntimeModule extends RuntimeModule {
  11. constructor() {
  12. super("publicPath", RuntimeModule.STAGE_BASIC);
  13. }
  14. /**
  15. * @returns {string} runtime code
  16. */
  17. generate() {
  18. const { compilation } = this;
  19. const { scriptType, importMetaName, path } = compilation.outputOptions;
  20. const chunkName = compilation.getPath(
  21. JavascriptModulesPlugin.getChunkFilenameTemplate(
  22. this.chunk,
  23. compilation.outputOptions
  24. ),
  25. {
  26. chunk: this.chunk,
  27. contentHashType: "javascript"
  28. }
  29. );
  30. const undoPath = getUndoPath(chunkName, path, false);
  31. return Template.asString([
  32. "var scriptUrl;",
  33. scriptType === "module"
  34. ? `if (typeof ${importMetaName}.url === "string") scriptUrl = ${importMetaName}.url`
  35. : Template.asString([
  36. `if (${RuntimeGlobals.global}.importScripts) scriptUrl = ${RuntimeGlobals.global}.location + "";`,
  37. `var document = ${RuntimeGlobals.global}.document;`,
  38. "if (!scriptUrl && document) {",
  39. Template.indent([
  40. `if (document.currentScript)`,
  41. Template.indent(`scriptUrl = document.currentScript.src`),
  42. "if (!scriptUrl) {",
  43. Template.indent([
  44. 'var scripts = document.getElementsByTagName("script");',
  45. "if(scripts.length) scriptUrl = scripts[scripts.length - 1].src"
  46. ]),
  47. "}"
  48. ]),
  49. "}"
  50. ]),
  51. "// When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration",
  52. '// or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic.',
  53. 'if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser");',
  54. 'scriptUrl = scriptUrl.replace(/#.*$/, "").replace(/\\?.*$/, "").replace(/\\/[^\\/]+$/, "/");',
  55. !undoPath
  56. ? `${RuntimeGlobals.publicPath} = scriptUrl;`
  57. : `${RuntimeGlobals.publicPath} = scriptUrl + ${JSON.stringify(
  58. undoPath
  59. )};`
  60. ]);
  61. }
  62. }
  63. module.exports = AutoPublicPathRuntimeModule;