Skip to content

Not working with expo #468

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
2ico opened this issue Feb 20, 2024 · 38 comments
Closed

Not working with expo #468

2ico opened this issue Feb 20, 2024 · 38 comments

Comments

@2ico
Copy link

2ico commented Feb 20, 2024

Expo SDK: 49.0.0
After following the instructions at https://github.com/ai/nanoid#react-native , I get:

Android Bundling failed 403ms
The package at "node_modules/nanoid/index.js" attempted to import the Node standard library module "node:crypto".
It failed because the native React runtime does not include the Node standard library.
@ai
Copy link
Owner

ai commented Feb 20, 2024

Did you foolow that steps?

https://github.com/ai/nanoid?tab=readme-ov-file#react-native

@2ico
Copy link
Author

2ico commented Feb 20, 2024

Yes, I did

@ai
Copy link
Owner

ai commented Feb 20, 2024

Sorry, I have no idea or experience with Expo.

Try to ask Expo community.

@2ico
Copy link
Author

2ico commented Feb 20, 2024

I think the issue is here:
https://github.com/ai/nanoid/blob/61a087715a21d971dc9154c5726c818db0e42b27/index.js#L1C1-L1C50
The module imports the entire webCrypto from node:crypto.

In version 3 only the required function getRandomBytesAsync was imported:

let { getRandomBytesAsync } = require('expo-random')

@ai
Copy link
Owner

ai commented Feb 20, 2024

Nope, those are different files. Sync and async.

@2ico
Copy link
Author

2ico commented Feb 20, 2024

Async was removed in v5, right?

@ai
Copy link
Owner

ai commented Feb 20, 2024

Yes

@2ico
Copy link
Author

2ico commented Feb 20, 2024

So what is the status for expo compatibility?
I see someone was using expo here: #415

@ai
Copy link
Owner

ai commented Feb 20, 2024

Yes, it should work. This doc was written by Expo user.

@2ico
Copy link
Author

2ico commented Feb 20, 2024

Can I contact them?

@ai
Copy link
Owner

ai commented Feb 20, 2024

I don’t think it is polite. You should use StackOverflow and similar things if you want ask others to do your work.

Try also import index.browser.js version. Maybe react-native-get-random-values polyfill has issue with import.

@2ico
Copy link
Author

2ico commented Feb 20, 2024

I don't think it's impolite to contact the maintainer of a library.

@ai
Copy link
Owner

ai commented Feb 20, 2024

I am the maintainer. You want to contact some other developer who send PR to the library.

@2ico
Copy link
Author

2ico commented Feb 20, 2024

Anyway, how can I do this?

Try also import index.browser.js version. Maybe react-native-get-random-values polyfill has issue with import.

Could not find a declaration file for module 'nanoid/index.browser'. '/home/george/Documents/GAIO/expo/archie-expo/node_modules/nanoid/index.browser.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/nanoid` if it exists or add a new declaration (.d.ts) file containing `declare module 'nanoid/index.browser';`

@ai
Copy link
Owner

ai commented Feb 20, 2024

This is just a type warning not an error.

Does it works?

@2ico
Copy link
Author

2ico commented Feb 20, 2024

It works, with @ts-ignore

@ai
Copy link
Owner

ai commented Feb 20, 2024

Try the new Nano ID 5.0.6 with normal import { nanoid } from 'nanoid

@2ico
Copy link
Author

2ico commented Feb 20, 2024

It doesn't work, unfortunately. It's still using './index.js'.
Thanks for the quick attempt!

@2ico
Copy link
Author

2ico commented Feb 20, 2024

And I guess the release should include a ./index.browser.d.ts file to solve the error I got with TS.

@ai
Copy link
Owner

ai commented Feb 20, 2024

And I guess the release should include a ./index.browser.d.ts file to solve the error I got with TS.

Separeted manual import for browser version is not a long-term solution because you can't change import inside other libraries.

It was only a test.

@steida
Copy link
Contributor

steida commented Apr 28, 2024

I tried this patch but without a success

diff --git a/package.json b/package.json
index 0d10ada4dce6c02a339399e71c82860c70f3d12b..4fb2ab8de9093eae1bc590cd738019e5b40d0dfb 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
   "exports": {
     ".": {
       "browser": "./index.browser.js",
+      "react-native": "./index.browser.js",
       "default": "./index.js"
     },
     "./non-secure": "./non-secure/index.js",

Why RN doesn't pick browser.js is a mystery.

@danielsht86
Copy link

In case anyone is still running into this and this is helpful. We had this problem and had to do 2 separate things to get crypto resolved correctly in different situations:

  1. We had to do the metro.config.js adjustment to properly resolve the module in case it was being explicitly imported:
config.resolver.resolveRequest = (context, moduleName, platform) => {
  if (moduleName === 'crypto' || moduleName === 'node:crypto') {
    // when importing crypto, resolve to react-native-quick-crypto
    return context.resolveRequest(context, 'react-native-quick-crypto', platform);
  }
  // otherwise chain to the standard Metro resolver.
  return context.resolveRequest(context, moduleName, platform);
};

(note, we added the node:crypto clause in case it mattered for some imports, although we never confirmed this was helpful for any particular case.

  1. We also had to override global.crypto since index.browser.js was being imported by default in our case
import { install } from 'react-native-quick-crypto';
install();

With both of these, we covered all our bases

@steida
Copy link
Contributor

steida commented Jan 4, 2025

I tried this patch but without a success

diff --git a/package.json b/package.json
index 0d10ada4dce6c02a339399e71c82860c70f3d12b..4fb2ab8de9093eae1bc590cd738019e5b40d0dfb 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
   "exports": {
     ".": {
       "browser": "./index.browser.js",
+      "react-native": "./index.browser.js",
       "default": "./index.js"
     },
     "./non-secure": "./non-secure/index.js",

Why RN doesn't pick browser.js is a mystery.

The reason was probably my pnpm monorepo setup because it was picking nanoid from the root and not from apps/expo.
So I pnpm overrided nanoid to 5.0.7, and suddenly... the fix works!

 "pnpm": {
    "overrides": {
      "nanoid": "^5.0.7"
    },

@ai I manually patched nanoid package.json with this:

"exports": {
    ".": {
      "react-native": "./index.browser.js",

@bradleyayers
Copy link

Thanks @steida patching package.json with

"exports": {
    ".": {
      "react-native": "./index.browser.js",

worked for me too.

bradleyayers added a commit to haohao-how/haohaohow that referenced this issue Mar 6, 2025
ai pushed a commit that referenced this issue Mar 7, 2025
@ai
Copy link
Owner

ai commented Mar 7, 2025

Fixed in 5.1.3

@ai ai closed this as completed Mar 7, 2025
@steida
Copy link
Contributor

steida commented Mar 8, 2025

@ai Thank you! Can you please also fix 3? It's still required in monorepos where hoisting is required, e.g. https://github.com/byCedric/expo-monorepo-example?tab=readme-ov-file#pnpm-workarounds

@ai
Copy link
Owner

ai commented Mar 8, 2025

@steida why can't you use require(esm)? It was backported to Node.js 22 & 20.

@steida
Copy link
Contributor

steida commented Mar 12, 2025

There is no such thing in Expo AFAIK.

@ai ai reopened this Mar 12, 2025
@ai
Copy link
Owner

ai commented Mar 12, 2025

@steida I will backport fix on next week (sorry, going to the conf right now).

@ai
Copy link
Owner

ai commented Mar 15, 2025

The fix was backported in 3.3.10. Please try.

@ai ai closed this as completed Mar 15, 2025
@steida
Copy link
Contributor

steida commented Mar 16, 2025

You put it at the wrong place

"exports": {
     ".": {
+      "react-native": "./index.browser.js",

@ai
Copy link
Owner

ai commented Mar 16, 2025

@steida are you talking about 3.x or 5.x?

3.x (with CJS) doesn’t use exports

nanoid/package.json

Lines 34 to 37 in bb12e8a

"react-native": {
"./index.js": "./index.browser.js",
"./async/index.js": "./async/index.native.js"
},

If 5.x we have react-native below browser. Why it is a problem and why expo is using 3.x?

@ai
Copy link
Owner

ai commented Mar 16, 2025

BTW, I am planning to release 6.x soon. In this version we will stop using node:crypto (because we do not need to support Node.js 18 anymore).

@steida
Copy link
Contributor

steida commented Mar 16, 2025

This is my patch for nanoid 3.3.8:

diff --git a/package.json b/package.json
index b238dca3a6170717ff9cb165df2aae11b95af095..a95682b5af3c2fc05c4207175545ae7531a60e8f 100644
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
   "module": "index.js",
   "exports": {
     ".": {
+      "react-native": "./index.browser.js",
       "browser": "./index.browser.js",
       "require": {
         "types": "./index.d.cts",

The issue is React Native used in monorepo with pnpm where it must be hoisting enabled which means only one nanoid dependency and RN ecosystem still uses 3.

@steida
Copy link
Contributor

steida commented Mar 16, 2025

This is how package.json from node_modules looks like after the patch:

{
  "name": "nanoid",
  "version": "3.3.8",
  "description": "A tiny (116 bytes), secure URL-friendly unique string ID generator",
  "keywords": [
    "uuid",
    "random",
    "id",
    "url"
  ],
  "engines": {
    "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
  },
  "funding": [
    {
      "type": "github",
      "url": "https://github.com/sponsors/ai"
    }
  ],
  "author": "Andrey Sitnik <[email protected]>",
  "license": "MIT",
  "repository": "ai/nanoid",
  "browser": {
    "./index.js": "./index.browser.js",
    "./async/index.js": "./async/index.browser.js",
    "./async/index.cjs": "./async/index.browser.cjs",
    "./index.cjs": "./index.browser.cjs"
  },
  "react-native": "index.js",
  "bin": "./bin/nanoid.cjs",
  "sideEffects": false,
  "types": "./index.d.ts",
  "type": "module",
  "main": "index.cjs",
  "module": "index.js",
  "exports": {
    ".": {
      "react-native": "./index.browser.js",
      "browser": "./index.browser.js",
      "require": {
        "types": "./index.d.cts",
        "default": "./index.cjs"
      },
      "import": {
        "types": "./index.d.ts",
        "default": "./index.js"
      },
      "default": "./index.js"
    },
    "./package.json": "./package.json",
    "./async/package.json": "./async/package.json",
    "./async": {
      "browser": "./async/index.browser.js",
      "require": {
        "types": "./index.d.cts",
        "default": "./async/index.cjs"
      },
      "import": {
        "types": "./index.d.ts",
        "default": "./async/index.js"
      },
      "default": "./async/index.js"
    },
    "./non-secure/package.json": "./non-secure/package.json",
    "./non-secure": {
      "require": {
        "types": "./index.d.cts",
        "default": "./non-secure/index.cjs"
      },
      "import": {
        "types": "./index.d.ts",
        "default": "./non-secure/index.js"
      },
      "default": "./non-secure/index.js"
    },
    "./url-alphabet/package.json": "./url-alphabet/package.json",
    "./url-alphabet": {
      "require": {
        "types": "./index.d.cts",
        "default": "./url-alphabet/index.cjs"
      },
      "import": {
        "types": "./index.d.ts",
        "default": "./url-alphabet/index.js"
      },
      "default": "./url-alphabet/index.js"
    }
  }
}```

@ai
Copy link
Owner

ai commented Mar 16, 2025

@steida oh, I forgot that dual-publish autogenerate exports. And what change do we need?

@steida
Copy link
Contributor

steida commented Mar 17, 2025

Only this: #468 (comment)

@ai
Copy link
Owner

ai commented Mar 18, 2025

@steida fixed in 3.3.11 (I moved away from dual-publish and now have manual ESM/CJS dual package).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants