React Native で Unable to resolve module crypto の対処法
背景
現在関わっているプロジェクトでは monorepo を採用しており
React, React Native, Node.js などの複数のパッケージがある状態になっており、双方で使いたい処理などは共通パッケージに置いています。
今回共通パッケージに crypto.createCipheriv
を使うファイルを置いたところ、React Native でエラーが出る状態になりました。
エラーログ
error: Error: Unable to resolve module crypto from .../crypto.ts:
crypto could not be found within the project or in these directories:
../../node_modules
If you are sure the module exists, try these steps:
1. Clear watchman watches: watchman watch-del-all
2. Delete node_modules and run yarn install
3. Reset Metro's cache: yarn start --reset-cache
4. Remove the cache: rm -rf /tmp/metro-*
> 1 | import crypto from "crypto";
原因
React Native は Node.js で動いてるのではなく Hermes や JavaScript Core などの JavaScript エンジンを使っているため Node.js 内蔵のモジュールは動作をしないということです。共通のパッケージでは crypto
を使用していたため上記のエラーが出ました。
対応の調査
-
- npm の暗号化用のライブラリである crypto-js で crypto で書いていたコードをを代替できないかを調査しましたが crypto で使っていた
createCipheriv
などのメソッドが使うことができませんでした。
- npm の暗号化用のライブラリである crypto-js で crypto で書いていたコードをを代替できないかを調査しましたが crypto で使っていた
-
-
react-native-crypto
ではrn-nodeify
を使ってセットアップするのですが、rn-nodeify
はnode_modules
の中を書き換える仕組みな為、monorepo でうまく動きませんでした。
-
解決方法
react-native-crypto
にあった issue を参考に、metro.config.js
内のextraNodeModules
に
crypto-browserify を追加することで crypto が使用できるようになり解決しました
resolver: {
extraNodeModules: {
crypto: require.resolve("crypto-browserify"),
stream: require.resolve("readable-stream"),
},
},
crypto-browserify
の内部でstream
を使用しているのでreadable-stream
も追加する必要があります
今回はreact-native-crypto
ではなく、crypto-browserify
を使いました。react-native-crypto
ではreact-native-randombyte
を導入する必要があるのですが、ネイティブモジュールを使っているため、pod install
などをする必要がある分、パフォーマンスは優れてるものがあると思われます。
まとめ
React Native crypto
などのワードで検索をしても色々なやり方があったり、古い情報があったりして、解決するのに苦労しました。Node.js の crypto を React Native を使うことなどがあれば参考になれればと思います。
Discussion