Home

Awesome

Using node.js libraries in React Native

Tools like browserify and webpack have made it easy to use code originally written for node.js in the browser environment. And even when developing exclusively for the browser, the node.js standard library has a lot to offer with a powerful Buffer implementation that goes beyond what typed arrays can do, a stream API, URL parsing, etc., making node.js an appealing target platform for any Javascript developer.

The React Native packager

So where does that leave React Native? On paper, React Native is not necessarily tied to a particular packager, as it will happily load a Javascript bundle from a file or URL, regardless of how that bundle was prepared. So in theory, using browserify or webpack would be possible. In practice, though, things are a lot more complicated:

To cut a long story short, betting on the React Native packager makes a lot of sense for now.

So how can we use node.js libraries if we're stuck with the React Native packager?

Custom transformers

The React Native packager has a little known pluggable component called a transformer. This is a function that takes a given source file and (typically using Babel) transforms it so that all the funky ES2015 syntax is replaced with stuff that JavaScriptCore can parse. We can supply our own transformer, use a Babel helper called babel-plugin-rewrite-require, and include browserify's reimplementation of node's core libraries to make any piece of code originally written for node.js runnable inside React Native's environment.

How it works

  1. Create a rn-cli.config.js file at the top of your React Native project. This file gets loaded by the React Native cli to load additional configuration. You can use it to specify various options that you'd otherwise have to pass via command line arguments. Using command line arguments doesn't always work, however. For instance, the XCode project will automatically call the packager without allowing you specify additional arguments. Check out the rn-cli.config.js file in this project for a list of possible options it can specify and their explanation.

  2. Provide your own transformer implementation. Check out transformer.js in this project for an example that uses babel-plugin-rewrite-require to rewrite imports of core node.js modules to their browserify equivalents. The browserify polyfills are installed via the node-libs-browser package. npm3 is required to install this project so that all dependencies are installed in a flat directory structure.

  3. Ensure you're injecting the necessary symbols into the global namespace. A lot of node.js libraries expect Buffer and process (among others) to be available in the global namespace. See global.js in this project for an example.

  4. Write code as if you were using node. The crypto_example.js file in this project provides an example that uses node's stream and crypto modules. You can convince yourself that it works in standalone node.js by running node node.js. But thanks to the machinery implemented in the previous steps, it'll also work just fine (if a bit slowly) in React Native. Keep in mind, it's just an example...

Gotchas

The React Native packager is extremely sensitive to the following scenarios:

Feedback

I can't promise that I'll be able to respond to issues filed, but they're definiitely welcome. Even more so Pull Requests.