19

I'm writing a simple Twitter app using react-native. Using twit module to get twitter feeds and stream. Below is the code, it works fine node. However, when included into my react-native app, seeing error "Requiring unknown module "crypto"". Dependency seems to be myapp->twit->oauth->crypto (thats part of node v0.12.2). Any suggestions to get this working inside react-native environment?

var Twit = require('twit')
var T = new Twit({
    consumer_key:''
  , consumer_secret:''
  , access_token:''
  , access_token_secret:''
})
var filtered_tweets=[];
var error;
var isSuccess=false;

function getTweets(searchString){
    T.get('search/tweets',{q:searchString, count:100}, getResponse);
    }

function getResponse(err,data,response){
        if(err) { 
            handleGetErr(err); 
        }
        handleGetData(data.statuses);
    }

function handleGetErr(err){

    enter code here

    error = err;
    }

function handleGetData(data){
    data.map(function(tweet){
      var twit={
        twit:tweet.id,
        created_at:tweet.created_at,
        text:tweet.text,
        retweet_count:tweet.retweet_count,
        favorite_count:tweet.favorite_count
      };
      filtered_tweets.push(twit);
    });
    console.log(filtered_tweets);
    isSuccess=true;
}
getTweets("@sahaswaranamam");
module.exports = getTweets;

![attached][2]

Sahas
  • 3,046
  • 6
  • 32
  • 53

7 Answers7

12

The crypto module is a built-in Node module; React Native runs JS on JavaScriptCore (when on the device or simulator) and on Chrome itself (when using Chrome debugging), so modules that depend on built-in Node.js modules won't work. See the JavaScript Runtime section of the React Native docs for more info.

I'm not sure how hard it would be to integrate into a React Native app, but browser module bundlers like Browserify often have browser versions of core Node.js modules, like this one for crypto.

Michelle Tilley
  • 157,729
  • 40
  • 374
  • 311
  • Thanks. Is there any other similar oauth implementation within JavaScriptCore as a sample.. – Sahas Apr 24 '15 at 00:26
5

If you are using rn-nodeify as @emmby suggests, then you can use react-native-crypto. Instructions from the README:

  1. Install

    npm i --save react-native-crypto
    # install peer deps
    npm i --save react-native-randombytes
    react-native link react-native-randombytes
    # install latest rn-nodeify
    npm i --save-dev mvayngrib/rn-nodeify
    # install node core shims and recursively hack package.json files
    # in ./node_modules to add/update the "browser"/"react-native"
    # field with relevant mappings
    ./node_modules/.bin/rn-nodeify --hack --install
    
  2. rn-nodeify will create a shim.js in the project root directory

    // index.ios.js or index.android.js
    // make sure you use `import` and not require!  
    import './shim.js'
    // ...the rest of your code
    

But rn-nodeify also states:

If you're looking for a saner approach, check out ReactNativify. I haven't tested it myself, but I think philikon will be happy to help


With ReactNativify you create a rn-cli.config.js and then in a transformer.js you let Babel transform bundle dependencies using babel-plugin-rewrite-require:

// The following plugin will rewrite imports. Reimplementations of node
// libraries such as `assert`, `buffer`, etc. will be picked up
// automatically by the React Native packager.  All other built-in node
// libraries get rewritten to their browserify counterpart.

[require('babel-plugin-rewrite-require'), {
  aliases: {
    crypto: 'crypto-browserify',
    // ...
  },
  throwForNonStringLiteral: true,
}]

(Note: You can also do this in without these 2 js files directly in .babelrc)

(Note2: Though ReactNativify is the cleaner way, it is still giving me issues wiring up crypto.getRandomValues for production-use in RN. See this question)

Arnold Schrijver
  • 3,588
  • 3
  • 36
  • 65
  • 1
    Instead of creating your own babel transforms inside a `transformer.js`, inside of `rn-cli.config.js` you can export `extraNodeModules` and override node modules. For more information check out this issue on ReactNativify's repo https://github.com/philikon/ReactNativify/issues/4 – btav Aug 09 '17 at 13:54
  • This solved it for me: https://github.com/philikon/ReactNativify/issues/4#issuecomment-312136794 – eega Dec 28 '19 at 13:59
  • @Arnold After completing all process successfully, I am getting this error Invariant Violation: Module AppRegistry is not a registered callable module (calling runApplication) – Chandni Jan 12 '21 at 12:03
  • Sorry @Chandni but this is too long ago for me to be able to help, and things may have changed in the meantime. If you get new insights in solving your problems related to the Answer, I'd gladly update the text (or with sufficient reputation you can do so yourself). – Arnold Schrijver Jan 14 '21 at 09:39
2

You can use the rn-nodeify module to get crypto on react-native.

Add rn-nodeify to your devDependencies in package.json:

"devDependencies": {
  "rn-nodeify": "^6.0.1"
}

Add the following to the scripts section of the same file:

"scripts": {
  …
  "postinstall": "node_modules/.bin/rn-nodeify --install crypto --hack"
}

Be aware that rn-nodeify will modify your package.json.

More information available here: https://www.npmjs.com/package/rn-nodeify

emmby
  • 99,783
  • 65
  • 191
  • 249
  • 1
    Will this help if one of my react-native dependency uses "crypto"? I tried following the instruction you wrote but it doesn't seem to work. – Zhen Liu Oct 26 '16 at 01:51
  • @emmby After completing all process successfully, I am getting this error Invariant Violation: Module AppRegistry is not a registered callable module (calling runApplication) – Chandni Jan 12 '21 at 12:03
2

React Native packager uses Babel under the hood. This means that you can use babel-plugin-rewrite-require Babel plugin to rewrite all require('crypto') calls to require('crypto-browserify'), assuming that the latter is installed in your node_modules.

As of January 2016, you can use .babelrc file to define optional configuration, so this becomes really easy. First, install the dependencies:

npm install --save crypto-browserify
npm install --save-dev babel-plugin-rewrite-require

Then add plugins config to your .babelrc file:

{
  "presets": ["react-native"],
  "plugins": [
    ["babel-plugin-rewrite-require", {
      "aliases": {
        "crypto": "crypto-browserify"
      }
    }]
  ]
}

Restart the packager and that should be it.

This is the same approach that ReactNativify uses, except that here we use .babelrc instead of defining custom transformer. When ReactNativify was written, it was not supported, so they had to go with more complex solution. See this file from ReactNativify for almost complete list of node polyfills.

Wilco Bakker
  • 527
  • 1
  • 7
  • 18
skozin
  • 3,789
  • 2
  • 21
  • 24
  • I understood your answer, but it is not working for some reason. "UnableToResolveError: Unable to resolve module stream from /Users/myproject/node_modules/browserify-sign/browser/index.js:" – Oximer Jan 05 '18 at 19:32
  • What module you were trying to rewrite? Do you have `stream` package in your `node_modules` directory? – skozin Jan 06 '18 at 15:23
  • @skozin thank for the reply! I still cannot make it work for a lib that relies on crypto. The lib is called: `otplib`. Did you find a way how to handle these cases? I managed to hack it with rn-nodeify but it is super agly – Petro Mar 11 '18 at 12:39
  • @skozin After completing all process successfully, I am getting this error Invariant Violation: Module AppRegistry is not a registered callable module (calling runApplication) – Chandni Jan 12 '21 at 12:04
0

I was having the same issue when implementing the Twilio package in my React Native app, and having React Native break over the crypto dependency.

As a work around I ended up creating a separate, stand alone Node/Express app to act as my server and take care of the Twilio logic I had. That way I removed all Twilio logic from my React Native app and moved it to Node. I then just called my Express route in React Native using fetch, which triggered the functionality I wanted to happen with Twilio. If you're unfamiliar with fetch here's a good starting point - Making AJAX calls with Fetch in React Native

In addition, here's my question on the crypto dependency breaking my app:

twilio-react-native-unable-to-resolve-module-crypto

Community
  • 1
  • 1
Onaracs
  • 935
  • 3
  • 14
  • 22
0

As far I can see amazon-cognito-identity-js uses crypto-js 3.3.0 without any additional magic... If that version of the package works then perhaps try that.

Erik Poromaa
  • 139
  • 2
  • 8
0

After having tried a bunch of these solutions and never really having been satisfied with any of them (some didn't even work), I managed to stumble upon react-native-quick-crypto, which honestly worked much more effortlessly than trying to lift the existing crypto library to the front-end

Electric Coffee
  • 11,733
  • 9
  • 70
  • 131