calvinmetcalf / rollup-plugin-node-builtins

138 stars 40 forks source link

Plugin wont build dependencies of uuid which are nodeJs builtins #37

Open judeantony opened 6 years ago

judeantony commented 6 years ago

I'm using UUID module to generate a random number which uses the nodeJS built in crypto module. Looks like this plugin is not able to resolve all the require done by the modules that are dependencies of uuid.

A repro of what I'm trying to explain.

My rollup-config looks like this.

With this when I run the application I get below error in my browser console. referenceerror

Following the error, I went on commenting certain lines in the index.js of crypto-browserify in node-modules to find that plugin was finally able to work as expected. Find below the commented lines in the file. It would be great if this plugin finds a way to fix this issue.

'use strict'

exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = require('randombytes')
exports.createHash = exports.Hash = require('create-hash')
exports.createHmac = exports.Hmac = require('create-hmac')

var algos = require('browserify-sign/algos')
var algoKeys = Object.keys(algos)
var hashes = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5', 'rmd160'].concat(algoKeys)
exports.getHashes = function () {
  return hashes
}

/*
  var p = require('pbkdf2')
   exports.pbkdf2 = p.pbkdf2
   exports.pbkdf2Sync = p.pbkdf2Sync

   var aes = require('browserify-cipher')

  exports.Cipher = aes.Cipher
  exports.createCipher = aes.createCipher
  exports.Cipheriv = aes.Cipheriv
  exports.createCipheriv = aes.createCipheriv
  exports.Decipher = aes.Decipher
  exports.createDecipher = aes.createDecipher
  exports.Decipheriv = aes.Decipheriv
  exports.createDecipheriv = aes.createDecipheriv
  exports.getCiphers = aes.getCiphers
  exports.listCiphers = aes.listCiphers
*/

var dh = require('diffie-hellman')

exports.DiffieHellmanGroup = dh.DiffieHellmanGroup
exports.createDiffieHellmanGroup = dh.createDiffieHellmanGroup
exports.getDiffieHellman = dh.getDiffieHellman
exports.createDiffieHellman = dh.createDiffieHellman
exports.DiffieHellman = dh.DiffieHellman

/*
  var sign = require('browserify-sign')

  exports.createSign = sign.createSign
  exports.Sign = sign.Sign
  exports.createVerify = sign.createVerify
  exports.Verify = sign.Verify

  exports.createECDH = require('create-ecdh')

  var publicEncrypt = require('public-encrypt')

  exports.publicEncrypt = publicEncrypt.publicEncrypt
  exports.privateEncrypt = publicEncrypt.privateEncrypt
  exports.publicDecrypt = publicEncrypt.publicDecrypt
  exports.privateDecrypt = publicEncrypt.privateDecrypt
*/

// the least I can do is make error messages for the rest of the node.js/crypto api.
// ;[
//   'createCredentials'
// ].forEach(function (name) {
//   exports[name] = function () {
//     throw new Error([
//       'sorry, ' + name + ' is not implemented yet',
//       'we accept pull requests',
//       'https://github.com/crypto-browserify/crypto-browserify'
//     ].join('\n'))
//   }
// })

var rf = require('randomfill')

exports.randomFill = rf.randomFill
exports.randomFillSync = rf.randomFillSync

exports.createCredentials = function () {
  throw new Error([
    'sorry, createCredentials is not implemented yet',
    'we accept pull requests',
    'https://github.com/crypto-browserify/crypto-browserify'
  ].join('\n'))
}

exports.constants = {
  'DH_CHECK_P_NOT_SAFE_PRIME': 2,
  'DH_CHECK_P_NOT_PRIME': 1,
  'DH_UNABLE_TO_CHECK_GENERATOR': 4,
  'DH_NOT_SUITABLE_GENERATOR': 8,
  'NPN_ENABLED': 1,
  'ALPN_ENABLED': 1,
  'RSA_PKCS1_PADDING': 1,
  'RSA_SSLV23_PADDING': 2,
  'RSA_NO_PADDING': 3,
  'RSA_PKCS1_OAEP_PADDING': 4,
  'RSA_X931_PADDING': 5,
  'RSA_PKCS1_PSS_PADDING': 6,
  'POINT_CONVERSION_COMPRESSED': 2,
  'POINT_CONVERSION_UNCOMPRESSED': 4,
  'POINT_CONVERSION_HYBRID': 6
}
calvinmetcalf commented 6 years ago

per the readme of this repo

Crypto is not shimmed and and we just provide the commonjs one from browserify and it will likely not work, if you really want it please pass {crypto: true} as an option.

sorry, you're better off browserifing uuid and then bringing that in or shimming it somehow to just grab the randomBytes module somehow

hanginwithdaddo commented 6 years ago

We are facing the same problem, but the uuid module is being included by some other module that we are using. I thought there should be a way of marking 'crypto' as 'external', such that the require('crypto') statements would be ignored, and then use the 'globals' list to map 'crypto' references to what 'builtins({ crypto: true }' brings in (cryptoBrowserify?, e.g., map things such that a reference to crypto.functionName() becomes cryptoBrowserify.functionName() or something similar). However, we can't seem to get any combination of stuff that we've tried to work. Browserifying uuid or shimming it won't work in our case because it is referenced by some other module that is being included indirectly. @calvinmetcalf, do you have any other suggestions?

alex-r-bigelow commented 6 years ago

For replication purposes, I'm having the same problems described by @hanginwithdaddo. My specific use case is trying to bundle pouchdb-browser, which requires uuid. Enabling the { crypto: true } option fixes this error:

Uncaught TypeError: crypto.randomBytes is not a function

But yields this error instead:

Uncaught TypeError: Cannot read property 'pbkdf2Sync' of undefined

The latter error references this line: https://github.com/crypto-browserify/pbkdf2/blob/d7882f117fa5eab9b80c5e53843f8d611c5ffc5d/index.js#L7

It looks like some kind of deep circular reference? Where crypto-browserify's pbkdf2 package requires the node crypto instead of crypto-browserify? I probed both repositories and can't seem to find a relevant issue to link here.

I tried messing around with rollup-plugin-replace to force all references to require('crypto') to change to require('crypto-browserify'), but that didn't seem to help (total rollup n00b here).

alex-r-bigelow commented 6 years ago

... and for anyone reaching this via Google, here's a temporary workaround until this is fixed:

EDIT: as of 2 May 2018, this workaround no longer appears to be necessary; the above errors seem to have been fixed

npm install rollup-plugin-replace randombytes

In your rollup.config.js file:

import replace from 'rollup-plugin-replace';

export default [
  ...
  {
    ...
    plugins: [
      replace({
        include: ['node_modules/uuid/**'],
        delimiters: ['', ''],
        values: {
          'crypto.randomBytes': 'require(\'randombytes\')'
        }
      }),
      resolve({ ... }),
      commonjs(),
      builtins(), // Note: do NOT include the { crypto: true } option here!
      globals(),
      ...
    ]
    ...
  }
  ...
];