-
-
Notifications
You must be signed in to change notification settings - Fork 31
Description
Context
Recently a fallback on the resolve module was removed in: 67076ff#diff-e727e4bdf3657fd1d798edcd6b099d6e092f8573cba266154583a746bba0f346L73-L82 This was part of the 8.0.0 release.
This fallback seems not to have been intended to support resolving external modules from inside bundled code, but as a side effect it actually did. When bundling code with Webpack, at runtime Webpack provides its own loader instead of the node.js native require.resolve. In short this means that when using require.resolve inside code bundled with Webpack, it can only resolve modules that are contained in the bundle. So external modules can't possibly be resolved this way.
The above linked commit basically removes a fallback to the resolve module for when (require.resolve && require.resolve.paths) doesn't evaluate to truthy. Webpack doesn't have require.resolve.paths on its "stubbed" require.resolve since it isn't useful / needed for the way that module resolution works in the Webpack runtime. So the check would fail since the require.resolve.paths is undefined (and thus falsy). This lead to the resolve module being used instead, with which you were able to actually resolve those external modules.
The reason I found this was because we did some dependency upgrades in the https://github.com/open-telemetry/opentelemetry-lambda layer for nodejs. Upgrading instrumentation libraries that use RITM indirectly through @opentelemetry/instrumentation. The latter upgraded the RITM version from 7.1.1 to 8.0.0. And now since the code for the node.js layer is bundled with Webpack, that means RITM inside our bundle will be actually using Webpack's stubbed require.resolve. This results in breaking instrumentation that needs to hook any non-core modules through RITM. Because those modules need to be external (not included in the bundle) for instrumentation libraries to be able to detect them being loaded.
Solutions
We have temporarily fixed this in the lambda layer by externalizing RITM from the webpack bundle (open-telemetry/opentelemetry-lambda#2037), but would like to see if any alternative solutions are possible.
I suppose the removal of the resolve module was a very deliberate choice to reduce footprint / increase performance?
One solution I could think of would be to have some check for when ritm is running inside a webpack bundle, pseudo-code but could look something like this:
function resolve (moduleName, basedir) {
let _resolve = function (moduleName, basedir) {
return require.resolve(moduleName, { paths: [basedir] })
}
if (webpackDetected) {
_resolve = function (moduleName, basedir) {
return __non_webpack_require__.resolve(moduleName, { paths: [basedir] })
}
}
}