Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Built-in alternative to babel-plugin-rewrite-require (extraNodeModules) #4

Open
parshap opened this issue Feb 19, 2017 · 15 comments
Open

Comments

@parshap
Copy link

parshap commented Feb 19, 2017

Update

See this library for convenience: https://github.com/parshap/node-libs-react-native

And this gist for more details: https://gist.github.com/parshap/e3063d9bf6058041b34b26b7166fd6bd

Original post

The React Native Packager has a built-in option, extraNodeModules, which seems to act as a module alias mapping. I couldn't find much information about this option, but here's the PR where it was added: facebookarchive/node-haste#69. Here's my rn-cli.config.js:

const extraNodeModules = require('node-libs-browser');

module.exports = {
  extraNodeModules,
};

And it seems to be working! I had to find this alternative approach because babel-plugin-rewrite-require was failing on a module with a dynamic require: readable-stream does require('st'+'ream').

This may be a better approach than using babel-plugin-rewrite-require because it doesn't need a custom transformer.js or a static mapping in .babelrc, and it seems to work on dynamic requires!

@davidaurelio: Is this an appropriate use of the extraNodeModules option?

/cc @mvayngrib

@mvayngrib
Copy link

@parshap thanks for cc'ing me, hope to check it out very soon!

@philikon
Copy link
Owner

philikon commented Mar 7, 2017

Woah! I'll check it out for sure!

And it seems to be working! I had to find this alternative approach because babel-plugin-rewrite-require was failing on a module with a dynamic require: readable-stream does require('st'+'ream').

This is what the throwForNonStringLiteral option in babel-plugin-rewrite-require is meant for. You want to enable it when you're using browserify modules (e.g. via node-libs-browser).

@wswoodruff
Copy link

Hey @parshap I'm running react-native 0.44.1 here, tried the extraNodeModules approach with node-libs-browser and I'm getting Unable to resolve net when trying to require a node package. Any reasons you can think of why that might not be working?

@parshap
Copy link
Author

parshap commented Jun 28, 2017

node-libs-browser doesn't include a "polyfill" for net. You'll have to include react-native-tcp.

Also check out https://www.npmjs.com/package/node-libs-react-native

@wswoodruff
Copy link

Yo @parshap! react-native-tcp is giving me this error when I require it in rn-cli.config.js:

.../project/path/node_modules/react-native-tcp/TcpSockets.js:16
exports.createServer = function(connectionListener: (socket: Socket)  => void) : Server {
                                                  ^
SyntaxError: Unexpected token :
    at Object.exports.runInThisContext (vm.js:76:16)

I'm not sure, I've also seen modules brought in via rn-cli.config.js trip over import statements. So confusing! Does rn-cli.config.js get babel transpiles or not? I'm using const and other es6 features, it didn't catch an object rest feature either. So it threw for that on:

{ ...extraNodeModules, net: require('react-native-tcp') }

@wswoodruff
Copy link

The only thing that works for me right now is this .babelrc file. I deleted my rn-cli.config.js!

{
  "presets": ["react-native"],
  "sourceMaps": true,
  "plugins": [
    ["rewrite-require", {
        "aliases": {
            "constants": "constants-browserify",
            "crypto": "react-native-crypto",
            "dns": "node-libs-browser/mock/dns",
            "domain": "domain-browser",
            "fs": "node-libs-browser/mock/empty",
            "http": "stream-http",
            "https": "https-browserify",
            "net": "node-libs-browser/mock/net",
            "os": "os-browserify/browser",
            "path": "path-browserify",
            "pbkdf2": "react-native-pbkdf2-shim",
            "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": "node-libs-browser/mock/tls",
            "tty": "tty-browserify",
            "vm": "vm-browserify",
            "zlib": "browserify-zlib"
        },
        "throwForNonStringLiteral": true
    }]
  ]
}

and react-native-pbkdf2-shim looks like this in package.json:

"react-native-pbkdf2-shim": "git+https://[email protected]/wswoodruff/react-native-pbkdf2-shim.git",

@parshap
Copy link
Author

parshap commented Jul 5, 2017

@wswoodruff: extraNodeModules should have paths to packages, not imported packages themselves.

module.exports = {
  extraNodeModules: {
    ...extraNodeModules,
    net: require.resolve('react-native-tcp'),
  },
};

See what node-libs-react-native itself exports.

@tslater
Copy link

tslater commented Jul 26, 2017

@parshap I'm having trouble with your approach. Are you doing anything besides adding your rn-cli.config.js? I'm having trouble trying to load the bitcoin example. It seems like the module loading isn't working. I get:

bscript.compile is not a function. (In 'bscript.compile([OPS.OP_DUP, OPS.OP_HASH160, pubKeyHash, OPS.OP_EQUALVERIFY, OPS.OP_CHECKSIG])', 'bscript.compile' is undefined)

encode
    output.js:26:25
toOutputScript
    address.js:42:85
addOutput
    transaction_builder.js:592:43
example
    bitcoin_example.js:13:15
<unknown>
    rn.js:16:6
run
    browser.js:153:19
drainQueue
    browser.js:123:16
callTimer
    JSTimersExecution.js:96:8
callTimers
    JSTimersExecution.js:138:34
__callFunction
    MessageQueue.js:260:47
<unknown>
    MessageQueue.js:101:26
__guard
    MessageQueue.js:228:6
callFunctionReturnFlushedQueue
    MessageQueue.js:100:17

In the original file:
var bscript = require('../../script') seems to be loading an empty object, instead of the one exported in ../../script

cheung31 added a commit to concensus/react-native-ios-concensus that referenced this issue Oct 29, 2017
cheung31 added a commit to concensus/react-native-ios-concensus that referenced this issue Oct 29, 2017
cheung31 added a commit to concensus/react-native-ios-concensus that referenced this issue Oct 29, 2017
timothyej added a commit to blockfirm/pine-app that referenced this issue Mar 22, 2018
This commit installs packages that bip39 depends on that is not
available in React Native. It then uses babel-plugin-rewrite-require
to rewrite the requires for these dependencies to use the React
Native versions instead. And last it exposes some global variables
such as Buffer and process using globals.js.

This solution is based on the idea of ReactNativify:
https://github.com/philikon/ReactNativify

But has been made much simpler thanks to this thread:
philikon/ReactNativify#4
@mnzaki
Copy link

mnzaki commented Jun 4, 2019

For people arriving in the future:

To use this properly now you should edit your metro.config.js (not rn-cli.config.js anymore) and add a resolver section like so:

module.exports = {
  resolver: {
    extraNodeModules: {
      // Polyfills for node libraries
      "crypto": require.resolve("crypto-browserify"),
      "stream": require.resolve("stream-browserify")
    }
  },
  // other metro config, etc
}

extraNodeModules docs: https://facebook.github.io/metro/docs/en/configuration#extranodemodules

@pcowgill
Copy link

@philikon Do you think this ^ alternative approach is worth documenting in the README?

@pcowgill
Copy link

@parshap Would you consider updating your gist to say metro.config.js rather than rn-cli.config.js and to reflect the info in the comment in this issue that require('st'+'ream') is possible with babel-plugin-rewrite-require using the throwForNonStringLiteral option?

@parshap
Copy link
Author

parshap commented Dec 18, 2019

Updated, thanks! Can you clarify what you mean by the throwForNonStringLiteral option and make a specific suggestion in the gist?

@pcowgill
Copy link

@parshap Thanks!!

The author of ReactNativify mentioned that that's an option in babel-plugin-rewrite-require in this comment

Here is the feature itself:
https://www.npmjs.com/package/babel-plugin-rewrite-require#non-string-literals

I don't think there's a way to make suggestions in the gist directly other than adding a comment, but my suggestion would be to remove this line:

"not supporting require() calls with an expression (such as require('cyrp' + 'to'))."

...since it does support that if you use the throwForNonStringLiteral setting.

@eliw00d
Copy link

eliw00d commented Apr 30, 2021

Does this work if crypto is required by a dependency of a dependency? For example, we use yarn workspaces and have a shared library. That library depends on crypto-hash which requires crypto. If I set crypto as an extraNodeModule, will that get triggered for the library's usage of crypto? If not, what would be a way to get this to work?

@JamesGs1994
Copy link

JamesGs1994 commented Jan 3, 2023

getting error for fs: unable to resolve fs
I am using google cloud/logging package for logs
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants