Importing uuid in rollup ESM library creates an import statement for "crypto" in output file
Asked Answered
F

1

6

Edit: Added plugins configuration for more clarity


I am using uuid package in a rollup project. At first I was getting a warning for external dependency crypto. So I added external and output.globals in my rollup configuration:

export default [{
  input: '/path/to/input.js',
  external: ['crypto'],
  output: {
    file: '/path/to/output.esm.js',
    format: 'esm',
    ...
    globals: {
      crypto: 'crypto'
    }
  },
  plugins: [
    resolve({
      customResolveOptions: {
        moduleDirectory: 'node_modules'
      },
      preferBuiltins: true
    }),
    commonjs({
      namedExports: {
        uuid: ['v4']
      }
    })
  ]
}];

The warning is gone, but now I have an import statement in my output file:

output.esm.js

import crypto from 'crypto';
...

My question is will this work if I include output.esm.js in browser?

<script type="module" src="/path/to/output.esm.js"></script>
Farrar answered 27/1, 2020 at 19:27 Comment(2)
Are you using @rollup/plugin-node-resolve? If yes, can you show its config?Deloris
@Deloris I have updated my question to include plugin-node-resolve configurationFarrar
D
13

At first I was getting a warning for external dependency crypto

This is because Rollup doesn't know whether you want to use node's built-in crypto or an external package. @rollup/plugin-node-resolve's preferBuiltins is used to choose between one of these alternatives.

So I added external and output.globals in my rollup configuration

These options, together with preferBuiltins: true tell Rollup to use node's built-in crypto without bundling it (hence the import statement still present in the output file).

However if your target environment is the browser, you should use the browser alternative provided by uuid that relies on the Web Crypto API instead of node's crypto. To do this, the following Rollup config should be enough:

// rollup.config.js

export default [{
  input: ...,
  output: {
    file: ...,
    format: 'esm',
  },
  plugins: [
    resolve({
        browser: true, // This instructs the plugin to use
                       // the "browser" property in package.json
    }),
    commonjs(),
  ],
}];

Just out of curiosity:

My question is will this work if I include output.esm.js in browser?

<script type="module" src="/path/to/output.esm.js"></script>

No, it won't; mainly because browsers don't understand bare module specifiers (import crypto from 'crypto' instead of './path/to/crypto.js'). Also, as per your Rollup configuration crypto is treated as a nodejs built-in, which is not available in the browser unless bundled :)

Deloris answered 8/2, 2020 at 16:4 Comment(4)
Just one more question. Crypto module is vastly different from its browser counter part. I was looking at the source code of uuid and found a dependency on a method called getRandomBytes which is available in node API but missing in browser. Does this ensure that those are polyfilled? Or I am understanding it all wrong and the option browser: true will bundle node's crypto library as part of the output.Farrar
You got it right, it won't be bundled. Well, in principle - unless you want to directly use crypto - you shouldn't worry about polyfills: uuid's readme would mention that. Also, I would say this is a pretty good sign that getRandomBytes won't be called anywhere.Deloris
Confirming that for use of uuid in the browser, nodeResolve({ browser: true }) works. For the sake of searchability, the errors that occur without "browser: true" are: 1) In Rollup: "(!) Unresolved dependencies rollupjs.org/guide/en/… crypto (imported by node_modules/uuid/dist/esm-node/rng.js, node_modules/uuid/dist/esm-node/md5.js, node_modules/uuid/dist/esm-node/sha1.js)" and 2) In Chrome: "Uncaught TypeError: Failed to resolve module specifier "crypto". Relative references must start with either "/", "./", or "../"."Maximilianus
none of these options fix the issue for me. I've been trying several different layout libraries for react. Every one of them seems use crypto, probably for uuids, I get error mentioned in the question. browser:true was already in my nodeResolve, adding preferBuiltins: true didn't fix it. Any other ideas? My rollup.config.jsNye

© 2022 - 2024 — McMap. All rights reserved.