Shims

ESM/CJS interoperability

Shims

When you publish ESM and CommonJS output from the same source, two interop problems show up: CommonJS globals (__dirname, __filename, require) do not exist in ESM, and default-export shapes differ between the two module systems. Packem addresses both with two real options.

cjsInterop

cjsInterop enables CommonJS interop handling for ESM modules. It is a top-level BuildOptions field and defaults to false.

import { defineConfig } from '@visulima/packem/config'

export default defineConfig({
  cjsInterop: true,
})

When enabled, Packem applies its CommonJS-interop Rollup plugin and adjusts warning handling (for example, it suppresses the MIXED_EXPORTS warning that would otherwise fire). The plugin's own behaviour can be tuned through rollup.cjsInterop, which defaults to { addDefaultProperty: false }:

export default defineConfig({
  cjsInterop: true,
  rollup: {
    cjsInterop: {
      addDefaultProperty: true,
    },
  },
})

ESM __dirname / __filename / require shim

The ESM shim rewrites CommonJS-only globals so that code using __dirname, __filename, or a global require(...) keeps working when emitted as ESM. It is configured via rollup.shim (an EsmShimCjsSyntaxOptions | false).

The shim is only applied when both cjsInterop is truthy and rollup.shim is set. In source the gate is literally cjsInterop && rollup.shim — enabling one without the other does nothing.

export default defineConfig({
  cjsInterop: true,
  rollup: {
    shim: {
      // EsmShimCjsSyntaxOptions (e.g. include/exclude filters)
    },
  },
})

What the shim injects

The shim scans each chunk for __filename, __dirname, and global require(...) usage and, only when found, prepends the matching imports after the last static import. For example:

  • __filename / __dirnameimport __cjs_url__ from "node:url" (and node:path for __dirname)
  • global require(...)import __cjs_mod__ from "node:module"

Each injected line is marked with a // -- packem CommonJS … shim -- comment, so Packem will not double-shim already-shimmed output. To disable the shim entirely, set rollup.shim: false.


  • Bundler - Shims run on the Rollup backend
  • Package Exports - How ESM/CJS entries map to exports
  • Target - Node target affects which interop you need
Support

Contribute to our work and keep us going

Community is the heart of open source. The success of our packages wouldn't be possible without the incredible contributions of users, testers, and developers who collaborate with us every day.Want to get involved? Here are some tips on how you can make a meaningful impact on our open source projects.

Ready to help us out?

Be sure to check out the package's contribution guidelines first. They'll walk you through the process on how to properly submit an issue or pull request to our repositories.

Submit a pull request

Found something to improve? Fork the repo, make your changes, and open a PR. We review every contribution and provide feedback to help you get merged.

Good first issues

Simple issues suited for people new to open source development, and often a good place to start working on a package.
View good first issues