Skip to content

CommonJS Node.js Default Interop Case #635

@guybedford

Description

@guybedford
  • Rollup Plugin Name: @rollup/plugin-commonjs
  • Rollup Plugin Version: 15.0.0

Feature Use Case

This is an edge case of the Node.js ESM / CJS interop.

The Node.js ESM / CJS interop semantics are described in the following section of the documentation - https://nodejs.org/dist/latest-v15.x/docs/api/esm.html#esm_commonjs_namespaces.

Up until version 14, RollupJS actually exactly followed these Node.js semantics (unintentionally yes, but it did nonetheless!).

A good test example is the following:

main.js

import * as m from './dep.js';
console.log(m);

dep.js

exports.__esModule = true;
exports.default = 'asdf';

Running:

rollup main.js --plugin @rollup/plugin-commonjs > build.js
node build.js

For version 14 of the plugin we get the output:

[Object: null prototype] {
  __esModule: true,
  default: { __esModule: true, default: 'asdf' },
  __moduleExports: { __esModule: true, default: 'asdf' }
}

While for version 15 and up we get the output:

[Object: null prototype] { __esModule: true, default: 'asdf' }

That is, it was only as recently as this August that RollupJS started diverging from what is considered the Node.js interop at this point.

Feature Proposal

I would like to propose that RollupJS reconsider the default behaviour here and consider aligning with Node.js.

Webpack is specifically not going with Node.js alignment on this edge cases, but RollupJS still can.

I think this kind of thing is important to get good behaviours universally in the ecosystem moving between environments. And I don't think blindly following Webpack is the recipe for success necessarily even though it is the most tempting path due to the majority of the ecosystem expectations being built there.

I understand this is a difficult discussion though so the first thing to do is to remember that this is an edge case we are discussing. It already affects a minority of cases.

But these small edge cases are what define the development experience when working with JavaScript for many developers.

If we can improve these friction points and make the interops align then we do well by the ecosystem.

There is a decision here to be made in either aligning with Webpack or Node.js here. I'm pushing for the Node.js side, because I feel that as a platform it has a long future and that Node.js build workflows should be considered first class.

Since this behaviour has only been in the plugin for two months I don't think it unreasonable to consider making a breaking change to support this sort of thing, and it would be a step made by RollupJS as a project to improve future interop compatibiity.

Further discussion / questions / feedback on this topic very welcome.

//cc @LarsDenBakker @lukastaegert @shellscape

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions