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
andoptimization: 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: