Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use browserified libraries in React Native

I have a library that I want to use in a React Native project that has been browserified. When I require the library all of the internal require() calls get hijacked and rather than resolve dependencies inside of the file that I am including React Native tries to resolve them, thus causing it to break. I'd like to know what the proper way to include a browserified library in a React Native project is.

like image 534
stanlemon Avatar asked Feb 22 '26 08:02

stanlemon


2 Answers

If you decide to use the method advised by ReactNativify, as suggested by Philipp von Weitershausen, then you should be aware of some considerations and tips (originally posted here):

1) I followed the advice I found in the issue list and split up transformer.js into 2 parts:

transformers.js (in /config and invoked from rn-cli.config.js):

const babelTransformer = require('./babel-transformer');

module.exports.transform = function(src, filename, options) {

    const extension = String(filename.slice(filename.lastIndexOf('.')));
    let result;

    try {

        result = babelTransformer(src, filename);

    } catch (e) {

        throw new Error(e);
        return;
    }

    return {
        ast: result.ast,
        code: result.code,
        map: result.map,
        filename
    };
};

babel-transformer.js (also in /config):

'use strict'

const babel = require('babel-core');

/**
 * This is your `.babelrc` equivalent.
 */
const babelRC = {
    presets: ['react-native'],
    plugins: [

    // 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: {
            constants: 'constants-browserify',
            crypto: 'react-native-crypto',
            dns: 'mock/dns',
            domain: 'domain-browser',
            fs: 'mock/empty',
            http: 'stream-http',
            https: 'https-browserify',
            net: 'mock/net',
            os: 'os-browserify/browser',
            path: 'path-browserify',
            pbkdf2: 'react-native-pbkdf2-shim',
            process: 'process/browser',
            querystring: 'querystring-es3',
            stream: 'stream-browserify',
            _stream_duplex: 'readable-stream/duplex',
            _stream_passthrough: 'readable-stream/passthrough',
            _stream_readable: 'readable-stream/readable',
            _stream_transform: 'readable-stream/transform',
            _stream_writable: 'readable-stream/writable',
            sys: 'util',
            timers: 'timers-browserify',
            tls: 'mock/tls',
            tty: 'tty-browserify',
            vm: 'vm-browserify',
            zlib: 'browserify-zlib'
        },
        throwForNonStringLiteral: true
    }],

    // Instead of the above you could also do the rewriting like this:

    ["module-resolver", {
      "alias": {
        "mock": "./config/mock",
        "sodium-universal": "libsodium"
      }
    }]
    ]
};

module.exports = (src, filename) => {

    const babelConfig = Object.assign({}, babelRC, {
    filename,
    sourceFileName: filename
    });

    const result = babel.transform(src, babelConfig);
    return {
    ast: result.ast,
    code: result.code,
    map: result.map,
    filename
    };
}

2) As you can see in the code above, I also demonstrated using the babel-plugin-module-resolver.

Note, I will use this plugin instead of the one ReactNative uses. It allows you to reference local files, and written with proper quotes allows non-JS-compliant names like 'sodium-universal'

Note2 Or go for .babelrc solution (maybe cleanest) as outlined in this comment: https://github.com/philikon/ReactNativify/issues/4#issuecomment-312136794

3) I found that I still needed a .babelrc in the root of my project to make my Jest tests work. See this issue for details: https://github.com/philikon/ReactNativify/issues/8

like image 65
Arnold Schrijver Avatar answered Feb 27 '26 02:02

Arnold Schrijver


The best solution I've come up with is to switch to webpack. As alluded to in one of the comments the library needs to be processed by something like browserify or web pack because it has decencies on node builtins like 'domain'. The problem is that browserify declares a require() method, which does not play nice inside of React Native which also has a require() method. Switching to webpack resolved this because they name their require() differently, __webpack_require() and this allows the processed version to work correctly inside of React Native.

like image 28
stanlemon Avatar answered Feb 27 '26 03:02

stanlemon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!