Falso attempts to import the built-in Node.js `crypto` module in the browser
srmagura opened this issue · 1 comments
Is this a regression?
No
Description
If you import any function from Falso in the browser, you'll get a warning similar to the following from your bundler:
Module "crypto" has been externalized for browser compatibility. Cannot access "crypto.randomBytes" in client code. See http://vitejs.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details.
It happens because Falso or one of its dependencies is attempting to import the crypto
module. This module is part of Node.js and is not available in the browser.
You can work around the issue by aliasing crypto
to a polyfill like crypto-browserify. But this is not recommended because that polyfill is very large.
Please provide a link to a minimal reproduction of the bug
https://github.com/srmagura/falso-crypto-repro
Please provide the exception or error you saw
Module "crypto" has been externalized for browser compatibility. Cannot access "crypto.randomBytes" in client code. See http://vitejs.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details.
Please provide the environment you discovered this bug in
Node 18, Vite 4.3.8, @ngneat/falso 6.4.0
Anything else?
I did a quick search in the Falso codebase, and it seems that Falso itself is not importing crypto
. So it must be one of Falso's dependencies that is importing it.
Do you want to create a pull request?
Yes
Root Cause
The line of code that is causing the problem is in the seedrandom
package here: https://github.com/davidbau/seedrandom/blob/4460ad325a0a15273a211e509f03ae0beb99511a/seedrandom.js#L236
Since the require
is wrapped in a try-catch
, it should be harmless. But bundlers don't know that. I think silencing the warning emitted by the bundler is a fine temporary solution in this case.
How to Silence the Warning
Webpack
If using Webpack, put this in your webpack.config.js
:
resolve: {
/* ... */
fallback: {
// For falso. This tells Webpack to not include a polyfill (since their
// bundle sizes are massive)
crypto: false,
stream: false,
},
},
Vite
If using Vite, create a file called src/emptyModule.ts
:
// See `vite.config.ts` for why this exists
export {};
Then, add this to your vite.config.ts
:
resolve: {
alias: {
crypto: 'src/emptyModule.ts',
},
},