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.
-
why not use the npm version? – Peter Gelderbloem Nov 24 '16 at 10:19
-
The library in question depends on built in node libraries like 'events' or 'domain' and while something like 'events' can be added as a dependency and just work, 'domain' is actually 'domain-browser' and so require stamens needs to be replaced by something like browserify. – stanlemon Nov 25 '16 at 13:29
-
Could you please share the web pack config and the command to create the bundle in React Native. I am getting few errors while using WebPack with React Native. – Gowthaman Aug 28 '19 at 06:39
-
You can see what I attempted in this PR: https://github.com/jsforce/jsforce/compare/master...stanlemon:lemon/webpack – stanlemon Aug 29 '19 at 11:57
3 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

- 3,588
- 3
- 36
- 65
-
Thanks, I did as you requested. You can remove the down-vote if you approve. – Arnold Schrijver Jul 20 '17 at 08:50
-
1Suggesting improvement, then down-voting and leaving is a bit rude @loki .. – Arnold Schrijver Jul 21 '17 at 10:51
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.

- 399
- 3
- 10
-
Can u share your webpack config ? I have tried both browserify and webpack bundles on my core node module and it still throws the same error in react native release apk. And runs just fine in debug mode . – spacedev Jul 23 '19 at 15:01
-
IMHO a better approach than browserifying a Node library is to
- use the browserify polyfills for Node built-ins like
crypto
,stream
, etc., - a small Babel transform to rewrite the
require()
calls fromcrypto
tocrypto-browserify
etc., - and the React Native packager itself to package it all up.
The ReactNativify repo demonstrates how to do all that.

- 4,623
- 1
- 16
- 5