Search code examples
dependenciesuuidguidcryptojsrollup

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


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>

Solution

  • 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 :)