Also, URLs didn't have to mean "exact version". A script provider might use a URL scheme with exact versions in it such as `/packagex/2.18.3/main.js` or could do semver-floating symlinks like `/packagex/2.18/main.js` for latest patch and `/packagex/2/main.js` for latest minor. You could even have hosts that just used the classic top-level `/packagex.js` for whatever is the latest.
I think the real problem with URL dependencies wasn't so much "exact versions", it was the confusing flexibility that versioning schemes were dependent on the package host because URLs are orthogonal/agnostic to version numbering and different package hosts can do whatever they wanted. (Naming conventions you'd have to look up for each/every host versus semver-aware package management code.)
Also, if multiple dependencies of yours share a sub-dependency, then unless they pick the exact same patch version then you're almost always going to have multiple versions of common sub-dependencies loaded. (It's great that multiple versions of a dependency can be loaded at once because it lets you avoid the classic "dependency hell" issue, but having multiple versions of nearly all of your common sub-dependencies gets wasteful at some point. Generally there's rarely a good reason to have multiple versions of the same dependency that only differ in patch or minor version.)
(Deno's current support for NPM and JSR avoids these issues.)