ulidx: Importing node:crypto breaks compat with edge runtimes (Vercel etc)
UnhandledSchemeError: Reading from "node:crypto" is not handled by plugins (Unhandled scheme).
Looks to have been an oversight(?) in https://github.com/perry-mitchell/ulidx/commit/5b90d022e54e122676fab8ac0c2470c3a05192bc
Reverting this commit fixes things.
Vercel edge runtime provides the web crypto API, which is not the same as / not one of the node-compatible modules that can be loaded with the node:
prefix: https://nextjs.org/docs/api-reference/edge-runtime
Big thanks for the work on this module!
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 2
- Comments: 28 (21 by maintainers)
2.0.0 released.
@jiw-mh Agreed, I’m going to add one now.
The sensible thing may be to provide a browser and node entry point →. https://github.com/uuidjs/uuid/blob/4de23a6030e65ac72b3b015680f08e7e292681ed/package.json#L24-L46
Thanks @perry-mitchell -
v2.0.0-1
solves the different entrypoints for node/browser and ESM/CJS in my testing, but the browser builds no longer resolve the globalcrypto
functions under the Vercel Edge runtime (and I suspect also Cloudflare Workers in general? Although I haven’t confirmed).The fix is straightforward - to update
detectRoot()
to check forglobalThis
- see #24(This wasn’t required when I tested the earlier version of your
web_build
branch as a result of the Webpack transformations, if I understand correctly.)Cheers!
@perry-mitchell It works with react-native again. Thank you! 🎉
@perry-mitchell Installed it in a project that is setup using vite and esm modules and it works fine.
So I’ve gone back on what I said and created a separate build for each environment anyway:
So they should all handle as you’d expect. If the tests work I’ll probably bundle and release this as 2.0.0 shortly.
You’re right, I’ll add that before merging - thanks!
I’m happy for someone to provide such an MR, but I don’t currently have the time to add it.
Big thanks @perry-mitchell - I checked out and built your web-build branch and patched that into my app and it does the job just fine. (NextJS, with both Webpack + Turbopack bundlers).
Point taken re: tree shaking - I think what you’ve added here gives a great combination of “quick to get it working, zero config” and “possible to optimise the bundling with a bit of work to tweak bundler config”. So thanks! 🙌
Regarding your exports - my only observation is you have a “browser” entry within the top-level “exports” field, but no top-level “browser” field for any bundlers/older versions that may not support package
"exports"
(unlike e.g.uuid
as referenced previously - see this line). It might be worth adding that also - although I don’t have a reference for which bundlers may still not support"exports"
.Got it! Thanks for explaining.
I figured a new solution that feels cleaner and causes the ESM import of the node crypto module to be stripped correctly - details below. My patch to achieve this is a bit scrappy but if this approach sounds useful I can try put together a tidier PR - let me know if it sounds promising!
~~
I’m using the default Webpack bundling config provided by Next.js (via
next dev
/next build
commands). With the current code this was failing with the error in my original post rather than stripping the import of the node crypto module as hoped.By patching the module in a different way I managed to solve the issue building for the Next.js Edge runtime (thus also I think for browser environments (?) although I haven’t verified). Specifically the Webpack bundler will strip the import of the node crypto module if it determines via tree-shaking that the import will never be referenced at runtime.
Webpack fails to tree-shake the current code seemingly due to the layers of indirection in the logic that first assigns to
globalCrypto
. To enable successful tree-shaking, I simply patched to add a simpleif
test that returns early with the result of the browser crypto API:This worked for my initial test - here I used the test
typeof EdgeRuntime === 'string'
as recommended specifically for the Vercel Edge runtime; I haven’t tested yet but I would next try some simplerif
tests to try achieve the tree-shaking based on availability of the web crypto API in the global scope rather than the (currently) vendor-specific test for the EdgeRuntime global.To be able to access the browser crypto API via the global
crypto.
I also renamed the import of the node crypto module (with ESM it may feel cleaner to instead import the required functions directly as named imports):To anyone else having these issues: please consider sticking with v0 for now… there’s no need to upgrade just yet as the feature set is the same.