Latest news about Bitcoin and all cryptocurrencies. Your daily crypto news habit.
Here’s a problem you might run into while using React Native: Let’s say you want to use the crypto module to create some hashes. It might seem natural to do something like this:
But this doesn’t work, because crypto is a core Node JS module, which means it’s probably C++ code bundled with the Node JS binary, not Javascript. The React Native packager can’t package it[1] along with your app’s Javascript bundle, so you get a runtime error: Unable to resolve module 'crypto'.
This makes core modules like crypto, stream etc. and the thousands of npm modules that depend on them unusable from React Native. Fortunately, there’s a solution to this problem, but it takes some work.
Solution
If you’re familiar the module bundler Browserify, you might know that it allows you to use core Node JS modules like crypto in the browser using polyfills[2]. So let’s try to create a standalone Javascript file that contains a polyfill for the crypto module, and use it within our app:
1. First, install browserify:
npm install -g browserify
2. Create a file crypto-in.js that imports the crypto module and simply exports it:
3. Create a standalone Javascript bundle crypto.js using browserify:
browserify crypto-in.js -o crypto.js
This creates a file crypto.js , which contains some 21,500 lines of code (containing the polyfills). The last few lines contain our code from crypto-in.js :
At this point, it might seem like we’re done, but we’re not! If you replace the line const crypto = require('crypto'); in the app code with const crypto = require('./crypto'); and try to run the app, you get the following error:
Turns out the word require is given special treatment by the React Native packager, and you can’t redefine it to mean something else, which is what Browserify tries to do within the bundle. If you look carefully inside crypto.js, you will notice that it always passes in a custom require function as a parameter and never actually uses the global require. There is a hacky but simple way to fix this problem, explained below.
4. Open the file crypto.js in a text editor, and replace all instances of the word require with something else e.g. reqqq . Make sure it’s unique, so it doesn’t conflict with any existing code and mess things up.
If you save crypto.js and reload the app now, the previous error will go away, but a new error will appear:
The packager isn’t able to find the method createHmac, because crypto isn’t exported properly from crypto.js. If you look at the last few lines of the bundle, you’ll find that this is because we’re setting module.exports not on the global modules object, but on something else that’s passed in as a function argument:
5. To export crypto properly from crypto.js, we need to make a few more changes to the file:
- Add the statement var crypto; at the top of the file to declare a new variable.
- Replace the statement var crypto = require('crypto'); with crypto = require('crypto'); to set the outer variable, instead of creating a local variable inside the function body.
- Move the line module.exports = crypto; outside the function body to the bottom of the file, so that it references the global module object.
After the changes, crypto.js should look something like this:
And that’s it! If you run the app now, it should all work perfectly:
Here’s a short summary of the steps it takes to use a core Node JS module like crypto (or something that depends on it) in a React Native app:
- Create a standalone Javascript bundle containing polyfills for the core modules using browserify (see crypto-in.js and crypto.js).
- Replace all instances of the require keyword inside the bundle with something unique e.g. reqqq, so that the React Native package manager leaves it alone.
- Export the crypto module correctly from the bundle, by importing it into a global variable, and setting the global module.exports to that variable (see the modified crypto.js).
Warning: The bundle generated by browserify can be rather large in size. For instance, the file crypto.js generated above is over 500kb in size. So keep an eye out for large bundles. Consider using a tool like Uglify to minify the bundle and reduce its size.
References
[1] — https://github.com/facebook/react-native/issues/1871[2] — https://github.com/substack/browserify-handbook#builtins[3] — https://github.com/facebook/react-native/issues/6253
Thanks for reading! I hope you’ve found this article helpful. Feel free to leave comments or suggestions. I would love to know if there is a better way to do this.
Using Core Node JS Modules in React Native Apps was originally published in Hacker Noon on Medium, where people are continuing the conversation by highlighting and responding to this story.
Disclaimer
The views and opinions expressed in this article are solely those of the authors and do not reflect the views of Bitcoin Insider. Every investment and trading move involves risk - this is especially true for cryptocurrencies given their volatility. We strongly advise our readers to conduct their own research when making a decision.