ESM & CJS: The subtle shift in bundlejs' behaviour
Tags: esm, javascript, typescript, cjs
Published: 2023-07-08 07:54:28

---
title: ESM & CJS: The subtle shift in bundlejs' behaviour
published: true
date: 2023-07-08 07:40:48 UTC
tags: esm, javascript, typescript, cjs
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/29bwg0jzj4esukzilqoi.jpg
canonical_url: https://blog.okikio.dev/changelog-july-8-2023-the-subtle-shift-in-bundlejs-behaviour
---

Greetings, fellow devs and bundlejs aficionados! 🚀

I was closing out some long lived issues over on [bundlejs](http://bundlejs.com), when issue [#50](https://github.com/okikio/bundlejs/issues/50) reminded me of the ongoing debate about how bundlejs should handle the ESM and CJS packages.

Lightbulbs flickered, coffee was consumed (I don't drink coffee, but you get the point), and I'm pretty sure I've cracked a solution. But there are a few slight behavior changes you need to be aware of. So buckle up. If anything looks off or confusing, please let me know in either the comments below, on [GitHub Discussions](https://github.com/okikio/bundlejs/discussions/53) or issues [#50](https://github.com/okikio/bundlejs/issues/50) directly.

## The Issue at Hand 🧐

The root of the problem lies in how bundlejs was handling CommonJS files.

> _"CommonJS files only export their default, which created a conundrum. How can we tell if a module is CommonJS if we don't fetch it? And if we fetch it first, it's too late for esbuild to deal with it properly."_

But never fear! I've worked out a solution that is impartial to whether the module is ESM or CommonJS.

## The Solution 🧩

Let's walk through this step by step, using our handy [deno.bundlejs.com](http://deno.bundlejs.com) API for demonstration.

1. **Single CJS File:** Only export the default (no renaming involved). Check out this example using `postcss-easings`: [https://deno.bundlejs.com/?file&q=postcss-easings&minify=false](https://deno.bundlejs.com/?file&q=postcss-easings&minify=false)
```ts
 // ...
 // virtual-filesystem:/index.ts
 var index_exports = {};
 __export(index_exports, {
   default: () => import_postcss_easings.default
 });
 __reExport(index_exports, __toESM(require_postcss_easings_4_0()));
 var import_postcss_easings = __toESM(require_postcss_easings_4_0());
 var export_default = import_postcss_easings.default;
 export {
   export_default as default
 };
```

2. **Multiple CJS Files:** Export the default but use the file URL as the import name. Also, append `...Default` to the end of it like so: `reactDefault` & `reactDomDefault`. Take a peek here: [https://deno.bundlejs.com/?file&q=react,react-dom&minify=false](https://deno.bundlejs.com/?file&q=react,react-dom&minify=false)
```ts 
 // ...
 // virtual-filesystem:/index.ts
 var index_exports = {};
 __export(index_exports, {
   reactDefault: () => import_react.default,
   reactDomDefault: () => import_react_dom.default
 });
 __reExport(index_exports, __toESM(require_react_18_2()));
 var import_react = __toESM(require_react_18_2());
 __reExport(index_exports, __toESM(require_react_dom_18_2()));
 var import_react_dom = __toESM(require_react_dom_18_2());
 var export_reactDefault = import_react.default;
 var export_reactDomDefault = import_react_dom.default;
 export {
   export_reactDefault as reactDefault,
   export_reactDomDefault as reactDomDefault
 };
```

3. **Single ESM File:** Export everything, including the default. No renaming here, folks! [https://deno.bundlejs.com/?file&q=spring-easing&minify=false](https://deno.bundlejs.com/?file&q=spring-easing&minify=false)
```ts
 // ...
 export {
   BatchSpringEasing,
   CSSSpringEasing,
   EaseInOut,
   EaseOut,
   EaseOutIn,
   EasingDurationCache,
   EasingFunctionKeys,
   EasingFunctions,
   EasingOptions,
   FramePtsCache,
   GenerateSpringFrames,
   INFINITE_LOOP_LIMIT,
   SpringEasing,
   SpringFrame,
   SpringInFrame,
   SpringInOutFrame,
   SpringOutFrame,
   SpringOutInFrame,
   batchInterpolateComplex,
   batchInterpolateNumber,
   batchInterpolateSequence,
   batchInterpolateString,
   batchInterpolateUsingIndex,
   SpringEasing as default, // <- The default export
   getLinearSyntax,
   getOptimizedPoints,
   getSpringDuration,
   getUnit,
   interpolateComplex,
   interpolateNumber,
   interpolateSequence,
   interpolateString,
   interpolateUsingIndex,
   isNumberLike,
   limit,
   parseEasingParameters,
   ramerDouglasPeucker,
   registerEasingFunction,
   registerEasingFunctions,
   scale,
   squaredSegmentDistance,
   toAnimationFrames,
   toFixed
 };
```

4. **Multiple ESM Files:** Export all methods and variables from all exports, but remember to use the naming rules for all default exports. For instance, after exporting the other module exports, rename the default export to `springEasingDefault` and `codepointIteratorDefault`: [https://deno.bundlejs.com/?file&q=spring-easing,codepoint-iterator&minify=false](https://deno.bundlejs.com/?file&q=spring-easing,codepoint-iterator&minify=false)
```ts
 // ...
 var mod_default = asCodePointsIterator;
 export {
   BITS_FOR_2B,
   BITS_FOR_3B,
   BITS_FOR_4B,
   BatchSpringEasing,
   CSSSpringEasing,
   EaseInOut,
   EaseOut,
   EaseOutIn,
   EasingDurationCache,
   EasingFunctionKeys,
   EasingFunctions,
   EasingOptions,
   FramePtsCache,
   GenerateSpringFrames,
   INFINITE_LOOP_LIMIT,
   LEAD_FOR_1B,
   LEAD_FOR_2B,
   LEAD_FOR_3B,
   LEAD_FOR_4B,
   LEAD_FOR_5B,
   MASK_FOR_1B,
   MASK_FOR_2B,
   MASK_FOR_3B,
   MASK_FOR_4B,
   SpringEasing,
   SpringFrame,
   SpringInFrame,
   SpringInOutFrame,
   SpringOutFrame,
   SpringOutInFrame,
   UTF8_MAX_BYTE_LENGTH,
   asCodePointsArray,
   asCodePointsCallback,
   asCodePointsIterator,
   batchInterpolateComplex,
   batchInterpolateNumber,
   batchInterpolateSequence,
   batchInterpolateString,
   batchInterpolateUsingIndex,
   bytesToCodePoint,
   bytesToCodePointFromBuffer,
   codePointAt,
   mod_default as codepointIteratorDefault, // <- codepoint-iterator's default export
   getByteLength,
   getIterableStream,
   getLinearSyntax,
   getOptimizedPoints,
   getSpringDuration,
   getUnit,
   interpolateComplex,
   interpolateNumber,
   interpolateSequence,
   interpolateString,
   interpolateUsingIndex,
   isNumberLike,
   limit,
   parseEasingParameters,
   ramerDouglasPeucker,
   registerEasingFunction,
   registerEasingFunctions,
   scale,
   SpringEasing as springEasingDefault, // <- spring-easing's default export
   squaredSegmentDistance,
   toAnimationFrames,
   toFixed
 };
```

5. **Treeshaking:** Here, we assume you want the driver's seat if you add the treeshake query param to the URL. So, all of the above rules are null and void, and you now have complete control over what is exported, including the default exports not being automatic. [https://deno.bundlejs.com/?file&q=spring-easing,react&treeshake=[\*],[\*]&minify=false](https://deno.bundlejs.com/?file&q=spring-easing,react&treeshake=[*],[*]&minify=false)
```ts
 // ...
 export {
   BatchSpringEasing,
   CSSSpringEasing,
   EaseInOut,
   EaseOut,
   EaseOutIn,
   EasingDurationCache,
   EasingFunctionKeys,
   EasingFunctions,
   EasingOptions,
   FramePtsCache,
   GenerateSpringFrames,
   INFINITE_LOOP_LIMIT,
   SpringEasing,
   SpringFrame,
   SpringInFrame,
   SpringInOutFrame,
   SpringOutFrame,
   SpringOutInFrame,
   batchInterpolateComplex,
   batchInterpolateNumber,
   batchInterpolateSequence,
   batchInterpolateString,
   batchInterpolateUsingIndex,
   getLinearSyntax,
   getOptimizedPoints,
   getSpringDuration,
   getUnit,
   interpolateComplex,
   interpolateNumber,
   interpolateSequence,
   interpolateString,
   interpolateUsingIndex,
   isNumberLike,
   limit,
   parseEasingParameters,
   ramerDouglasPeucker,
   registerEasingFunction,
   registerEasingFunctions,
   scale,
   squaredSegmentDistance,
   toAnimationFrames,
   toFixed
 };
 // ^ React isn't exported at all
```

> 🚨 Note: You might run into issues with CJS modules if you don't export default properly. Part of this is because tree-shaking is somewhat of a no-show for CJS packages, so tread lightly here!

There you have it! A quick and dirty rundown of the latest updates to the way [bundlejs.com](http://bundlejs.com) handles CJS and ESM packages.

So, go ahead and take the new system for a spin. Let me know what you think. Take it for a ride 🚗

![Car Salesman Slaps Roof Of Car Meme](https://i.imgflip.com/7rwjsv.jpg)

Photo by Marcin Jozwiak: [https://www.pexels.com/photo/abstract-red-and-white-waves-background-subtle-gradients-flow-liquid-lines-design-element-13835514/](https://www.pexels.com/photo/abstract-red-and-white-waves-background-subtle-gradients-flow-liquid-lines-design-element-13835514/)