Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
andersk opened this issue Aug 29, 2020 · 14 comments · Fixed by #1926 or #1927

Comments

@andersk
Copy link

andersk commented Aug 29, 2020

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

@andersk andersk changed the title [bug] pkg.main, pkg.module are incompatible, so require("sortablejs") behaves differently under Webpack [bug] pkg.main, pkg.module are incompatible, so require("sortablejs") behaves differently under Rollup/Webpack Aug 29, 2020
@waynevanson
Copy link
Contributor

I think option 3 sounds like the best option, but need to ensure no changes are breaking. I've also experienced troubles with this.

So are main and module supposed to be the same?

Some information:

@andersk
Copy link
Author

andersk commented Sep 15, 2020

Now with sortablejs@1.11.2-alpha.3 (did you mean to tag an alpha as latest?), require("sortablejs") doesn’t work at all in Node because pkg.main == "dist/sortable.js" is missing entirely.

$ npm i sortablejs

+ sortablejs@1.11.2-alpha.3
added 1 package and audited 1 package in 0.542s
found 0 vulnerabilities

$ node -e 'require("sortablejs")'
internal/modules/cjs/loader.js:328
      throw err;
      ^

Error: Cannot find module '/tmp/test/node_modules/sortablejs/dist/sortable.js'. Please verify that the package.json has a valid "main" entry
    at tryPackage (internal/modules/cjs/loader.js:320:19)
    at Function.Module._findPath (internal/modules/cjs/loader.js:533:18)
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:879:27)
    at Function.Module._load (internal/modules/cjs/loader.js:742:27)
    at Module.require (internal/modules/cjs/loader.js:964:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at [eval]:1:1
    at Script.runInThisContext (vm.js:132:18)
    at Object.runInThisContext (vm.js:309:38)
    at Object.<anonymous> ([eval]-wrapper:10:26) {
  code: 'MODULE_NOT_FOUND',
  path: '/tmp/test/node_modules/sortablejs/package.json',
  requestPath: 'sortablejs'
}

$ ls node_modules/sortablejs/dist
sortable.umd.js  sortable.umd.js.map

@liuestc
Copy link

liuestc commented Sep 16, 2020

I meet the same question , how to solve it?

@liuestc
Copy link

liuestc commented Sep 16, 2020

I meet the same question , how to solve it?

I solved it by
import Sortable from 'sortablejs/dist/sortable.umd';

@waynevanson
Copy link
Contributor

I'm pretty sure this was fixed by #1913, but looking closer it looks like I missed out on packaging Main.. Fixing now.

@waynevanson
Copy link
Contributor

@liuestc Try it without the work around, it should work with version alpha-4.

happens recently because of #1920

@andersk
Copy link
Author

andersk commented Sep 19, 2020

Still broken in 1.11.2-alpha.4 in a sort of reversed way:

  • in Node, require("sortablejs") returns a module {MultiDrag, Sortable, Swap, default};
  • in Browserify and Webpack, require("sortablejs") returns a function;
  • Rollup warns that sortablejs is an unresolved dependency and leaves in the require statement.

This time pkg.module == "dist/sortable.module.js" doesn’t exist, and pkg.browser == "dist/sortable.umd.js" is incompatible with pkg.main == "dist/sortable.js".

@waynevanson
Copy link
Contributor

Yeah okay thank you for your effort. I'll fix it tomorrow, don't have my computer one me right now.

@waynevanson
Copy link
Contributor

Do we even need the main field?
I think we can use module field and browser field.

https://docs.npmjs.com/files/package.json#browser

@andersk
Copy link
Author

andersk commented Sep 19, 2020

Without the main field, it won’t be possible to require("sortablejs") in Node at all. You might assume there’s no use case for this, but it comes up when writing unit tests for parts of modules that also happen to load sortablejs somewhere in their recursive imports; this is the case in Zulip.

@waynevanson
Copy link
Contributor

waynevanson commented Sep 20, 2020

@andersk Thank you for claryifying.

Almost done fixing the screw ups btw

@waynevanson waynevanson self-assigned this Sep 21, 2020
waynevanson added a commit that referenced this issue Sep 21, 2020
* refactor: remove code formattings config files

* docs: add more detail to contribution guidelines

* docs: remove custom templates

* docs: update bug report issue

* docs: add discussion template

* docs: update featue template

* fix(build): build dist/sortablejs, was missing prior

* build(deps): yarn upgrade

* v1.11.2-alpha.4

* fix(build): exports modules correctly

This was broken, visible, and closes #1891.
@andersk
Copy link
Author

andersk commented Sep 21, 2020

Thanks for your attention to this, but it’s still broken in 1.12.0; it’s back to what I wrote in the original description. Please reopen this.

@waynevanson
Copy link
Contributor

@andersk How about now? I removed the module and it now just Main.

@andersk
Copy link
Author

andersk commented Sep 21, 2020

I expect that will work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants