Skip to content

[bug] pkg.main, pkg.module are incompatible, so require("sortablejs") behaves differently under Rollup/Webpack #1891

@andersk

Description

@andersk

In some environments like Node and Browserify, require("sortablejs") returns Sortable, but in others like Rollup and Webpack, require("sortablejs") returns a module { Sortable: Sortable, default: Sortable, … }. This means a SortableJS dependent can’t be compatible with these different environments without contortions.

$ npm i browserify rollup @rollup/plugin-commonjs @rollup/plugin-node-resolve sortablejs webpack webpack-cli
$ echo 'console.log(require("sortablejs"))' > src.js
$ node src.js
[Function: Sortable] {
  utils: { … },
  get: [Function (anonymous)],
  mount: [Function (anonymous)],
  create: [Function (anonymous)],
  version: '1.10.2'
}
$ npx browserify src.js > out.js
$ node out.js
[Function: Sortable] {
  utils: { … },
  get: [Function (anonymous)],
  mount: [Function (anonymous)],
  create: [Function (anonymous)],
  version: '1.10.2'
}
$ npx rollup src.js -p node-resolve -p commonjs -f cjs -o out.js
$ node out.js
[Object: null prototype] {
  default: [Function: Sortable] {
    utils: { … },
    get: [Function (anonymous)],
    mount: [Function (anonymous)],
    create: [Function (anonymous)],
    version: '1.10.2'
  },
  MultiDrag: [Function: MultiDragPlugin],
  Sortable: [Function: Sortable] {
    utils: { … },
    get: [Function (anonymous)],
    mount: [Function (anonymous)],
    create: [Function (anonymous)],
    version: '1.10.2'
  },
  Swap: [Function: SwapPlugin]
}
$ npx webpack -d
$ node dist/main.js
Object [Module] {
  MultiDrag: [Getter],
  Sortable: [Getter],
  Swap: [Getter],
  default: [Function: Sortable] {
    utils: { … },
    get: [Function (anonymous)],
    mount: [Function (anonymous)],
    create: [Function (anonymous)],
    version: '1.10.2'
  }
}

This is because Node and Browserify are using pkg.main (./Sortable.js), while Rollup and Webpack are using pkg.module (modular/sortable.esm.js), and the two files do not provide compatible interfaces.

This problem is called out in the Rollup documentation:

Note: There are some tools such as Babel, TypeScript, Webpack, and @rollup/plugin-commonjs that are capable of resolving a CommonJS require(...) call with an ES module. If you are generating CommonJS output that is meant to be interchangeable with ESM output for those tools, you should always use named export mode. The reason is that most of those tools will by default return the namespace of an ES module on require where the default export is the .default property.

Three potential solutions are:

  • use named export mode, so require("sortablejs").default or require("sortablejs").Sortable would work everywhere; or
  • add Sortable.default = Sortable and/or Sortable.Sortable = Sortable for compatibility; or
  • remove pkg.module.

Information

Versions - Look in your package.json for this information:
sortablejs = ^1.10.2

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions