Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save cdn34/652cf62082ab778e02d5f07a084ba1c7 to your computer and use it in GitHub Desktop.

Select an option

Save cdn34/652cf62082ab778e02d5f07a084ba1c7 to your computer and use it in GitHub Desktop.

Revisions

  1. @parshap parshap revised this gist Apr 14, 2017. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions node-modules-in-react-native.md
    Original file line number Diff line number Diff line change
    @@ -53,6 +53,8 @@ not a widely used approach and as long as Facebook uses React Native
    Packager internally, React Native will work best with React Native
    Packager.

    [rn webpack]: https://github.com/mjohnston/react-native-webpack-server

    ### rn-nodeify

    [rn-nodeify][] works by editing all `package.json` files in
  2. @parshap parshap created this gist Apr 14, 2017.
    127 changes: 127 additions & 0 deletions node-modules-in-react-native.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,127 @@
    # Running Node Modules in React Native

    *How to use packages that depend on Node.js core modules in React
    Native.*

    ## Node.js Core Modules

    Node has several modules that are automatically available via
    `require()`: `http`, `crypto`, etc. While these modules are available
    in Node, they are not automatically available in other environments
    such as browsers and React Native.

    ### Browsers

    "Node-style" code (using modules and `require()`) that targets browsers
    is usually compiled using tools such as Webpack or Browserify. These
    compilers implement `require()` and other functionality normally
    available in Node but not browsers, including [Node core modules
    implemented for browser usage][node-libs-browsers].

    [node-libs-browsers]: https://github.com/webpack/node-libs-browser

    ### React Native

    Similar to the browsers scenario, React Native compiles "Node-style"
    code to run in the React Native environment via the [React Native
    Packager][]. The packager is similar to Webpack or Browserify, but with
    some minor differences, including having no official documentation or
    best practice for running Node core module.

    [react native packager]: https://github.com/facebook/react-native/tree/master/packager

    ## Why

    Usually, there are React Native-specific counterparts to the Node core
    modules that provide the same functionality, e.g.,
    [react-native-crypto][]. So why does one need Node core modules to work
    in React Native? **The answer is cross-platform code and the vast npm
    ecosystem.** It's convenient to be able to use the same modules in React
    Native as in Node and browsers.

    [react-native-crypto]: https://github.com/mvayngrib/react-native-crypto

    ## Prior Work

    There are several approaches to running Node core modules in React
    Native.

    ### Webpack for React Native

    While it's possible to use [Webpack with React Native][rn webpack], it's
    not a widely used approach and as long as Facebook uses React Native
    Packager internally, React Native will work best with React Native
    Packager.

    ### rn-nodeify

    [rn-nodeify][] works by editing all `package.json` files in
    `node_modules` to add the `react-native` field. Similar to the
    [`browser` field][browser field] in `package.json`, the `react-native`
    field tells the React Native Packager to substitute one modules with
    another (e.g., `crypto` with `react-native-crypto`). rn-nodeify also
    applies various other "hacks" to some sources files. See the [rn-nodeify
    readme][] for more information.

    This approach is less than ideal because it involves editing files in
    the `node_modules` directory and must be run after every time
    dependencies are changed.

    [rn-nodeify]: https://github.com/mvayngrib/rn-nodeify
    [rn-nodeify readme]: https://github.com/mvayngrib/rn-nodeify#what-it-does
    [browser field]: https://github.com/defunctzombie/package-browser-field-spec

    ### ReactNativify

    [ReactNativify][] documents how to use a custom React Native Packager
    transformer and the [`babel-plugin-rewrite-require`][babel rewrite]
    Babel plugin to support Node core modules. While this solution is
    robust, being wholly encapsulated by the packager without depending on
    editing files in `node_modules`, it's not ideal as it involves
    maintaining a complicated [transformer implementation][] and keeping it
    up to date with [Packager's implementation][packager transformer].
    `babel-plugin-rewrite-require` also has slightly different behavior than
    Webpack and Browserify, not supporting `require()` calls with
    an expression (such as `require('cyrp' + 'to')`).

    [ReactNativify]: https://github.com/philikon/ReactNativify
    [transformer implementation]: https://github.com/philikon/ReactNativify/blob/master/transformer.js
    [packager's implementation]: https://github.com/facebook/react-native/blob/master/packager/transformer.js

    ## `rn-cli.config.js` and `extraNodeModules`

    The best solution to running Node core modules in React Native is a
    built-in React Native Packager configuration option: `extraNodeModules`.
    This [little-known and undocumented feature][extraNodeModules] allows
    specifying modules that should be globally available as Node core
    modules. To use this configuration option, add a `rn-cli.config.js` file
    in the root directory of your React Native project:

    ```js
    module.exports = {
    extraNodeModules: {
    crypto: require('react-native-cyrpto'),
    },
    };
    ```

    For extra convenience, you can use the [node-libs-browser][] package to
    make all modules available:

    ```js
    module.exports = {
    extraNodeModules: require('node-libs-browser'),
    };
    ```

    [extraNodeModules]: https://github.com/facebookarchive/node-haste/pull/69

    ## Global Environment

    While the above solution will make it possible to `require()` Node core
    modules, "Node-style" code also expects the global environment to be in
    a specific state. The React Native global environment should be mutated
    to meet these expectations. See [ReactNativify's `global.js`][global]
    for an example of doing this.

    [global]: https://github.com/philikon/ReactNativify/blob/master/global.js