Skip to content

Wrong webpack automatic public path snippet injected for esm builds #13185

Closed

Description

Current Behavior

When using the web:webpack executor, and publicPath is auto (or missing, since it defaults to auto), the code injected for the automatic public path detection is wrong for esm builds.

Webpack has two different templates for this code, depending on if the script type is of type module, since document.currentScript does not work for module scripts:
https://github.com/webpack/webpack/blob/main/lib/runtime/AutoPublicPathRuntimeModule.js#L35-L65

The important line is this which checks for scriptType being module to inject the right snipet.

nx's default webpack config does not set the output.scriptType option when esm is enabled, so the wrong snippet gets injected.

Expected Behavior

Expected webpack to use import.meta.url for automatic public path instead of document.currentScript

Steps to Reproduce

I was able to reproduce by:

  • Create a brand new react workspace
  • Setting the executor to web:webpack
  • Create and lazily import a component via await import() to force webpack to inject the publicPath code
  • Building for production (esm: true and optimization: true)

In the minimized runtime chunk there's the following snippet:

if(!e&&r&&(r.currentScript&&(e=r.currentScript.src),!e))

If I manually disable minification to make it more readable, it looks like this:

/******/ 	/* webpack/runtime/publicPath */
/******/ 	(() => {
/******/ 		var scriptUrl;
/******/ 		if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + "";
/******/ 		var document = __webpack_require__.g.document;
/******/ 		if (!scriptUrl && document) {
/******/ 			if (document.currentScript)
/******/ 				scriptUrl = document.currentScript.src
/******/ 			if (!scriptUrl) {
/******/ 				var scripts = document.getElementsByTagName("script");
/******/ 				if(scripts.length) scriptUrl = scripts[scripts.length - 1].src
/******/ 			}
/******/ 		}
/******/ 		// When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration
/******/ 		// or pass an empty string ("") and set the __webpack_public_path__ variable from your code to use your own logic.
/******/ 		if (!scriptUrl) throw new Error("Automatic publicPath is not supported in this browser");
/******/ 		scriptUrl = scriptUrl.replace(/#.*$/, "").replace(/\?.*$/, "").replace(/\/[^\/]+$/, "/");
/******/ 		__webpack_require__.p = scriptUrl;
/******/ 	})();

Which is the wrong snippet from the webpack source (the non esm one)

Failure Logs

Environment

Node : 16.16.0
   OS   : darwin arm64
   npm  : 8.19.2

   nx : 15.0.13
   @nrwl/angular : Not Found
   @nrwl/cypress : 15.0.13
   @nrwl/detox : Not Found
   @nrwl/devkit : 15.0.13
   @nrwl/esbuild : Not Found
   @nrwl/eslint-plugin-nx : 15.0.13
   @nrwl/expo : Not Found
   @nrwl/express : Not Found
   @nrwl/jest : 15.0.13
   @nrwl/js : 15.0.13
   @nrwl/linter : 15.0.13
   @nrwl/nest : Not Found
   @nrwl/next : Not Found
   @nrwl/node : Not Found
   @nrwl/nx-cloud : Not Found
   @nrwl/nx-plugin : Not Found
   @nrwl/react : 15.0.13
   @nrwl/react-native : Not Found
   @nrwl/rollup : 15.0.13
   @nrwl/schematics : Not Found
   @nrwl/storybook : 15.0.13
   @nrwl/web : 15.0.13
   @nrwl/webpack : 15.0.13
   @nrwl/workspace : 15.0.13
   typescript : 4.8.4
   ---------------------------------------
   Local workspace plugins:
   ---------------------------------------
   Community plugins:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions