Search code examples
javascriptnode.jsrollup

Tailor dependencies to ES or CJS with Rollup


I have a NPM package (private) which works in both a browser and Node environment.

This is done by creating separate bundles via Rollup for ES and CJS, so the output looks like:

dist/ejs/index.js // Import this for your browswer environments
dist/cjs/index.js // Use this for Node environments

Pretty standard. Now I'm adding a dependency to this, which follows the same bundling pattern.

I can import the library like so:

import { externalLibrary } from "@external/ejs/externalLibrary";

All is good in a browser environment. But now this does not work in a Node environment, as what I'm importing is not CJS.

I could change the way I import the library to require and target the cjs bundle:

const { externalLibrary } = require("@external/cjs/externalLibrary");

And while this works in both environments, I don't think it's optimal.

Is there a better way of doing this? Some configuration that I could specify when exporting the CJS bundle?

module.exports = {
  input: 'src/main.js',
  output: {
    file: 'bundle.js',
    format: 'cjs'
    // Behaviour here for @external/cjs/externalLibrary ?
  }
};

Solution

  • I overlooked the package.json config. You can specify different entry files depending on the build here:

    {
      ...
      "main": "dist/cjs/index.js",
      "module": "dist/ejs/index.js",
      ...
    }
    

    Then I removed the implicit import of the EJS file, and targeted just the package:

    // Before:
    import { externalLibrary } from "@external/dist/ejs/externalLibrary";
    
    // After:
    import { externalLibrary } from "@external";
    

    This then ensures either the CJS or ES build is used, depending on the environment using the package.