turndown
turndown copied to clipboard
pkg.main, pkg.module are incompatible, so require("turndown") behaves differently under Rollup/Webpack
In Node, require("turndown")
returns TurndownService
, but in Rollup or Webpack, require("turndown")
returns { default: TurndownService }
. This means a Turndown dependent can’t be compatible with both environments without contortions.
$ npm i rollup @rollup/plugin-commonjs @rollup/plugin-node-resolve turndown webpack webpack-cli
$ echo 'console.log(require("turndown"))' > src.js
$ node src.js
[Function: TurndownService]
$ npx rollup src.js -p node-resolve -p commonjs -f cjs -o out.js
$ node out.js
{ default: [Getter] }
$ npx webpack --mode=development --target=node
$ node dist/main.js
Object [Module] { default: [Getter] }
This is because Node is using pkg.main
(lib/turndown.cjs.js
), while Rollup and Webpack are using pkg.module
(lib/turndown.es.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 CommonJSrequire(...)
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 usenamed
export mode. The reason is that most of those tools will by default return the namespace of an ES module onrequire
where the default export is the.default
property.
Three potential solutions are:
- use
named
export mode, sorequire("turndown").default
would work everywhere; or - add
TurndownService.default = TurndownService
for compatibility; or - remove
pkg.module
(and presumablypkg["jsnext:main"]
).
I'm currently facing this issue in an environment that runs both in Node and a webworker. Is there a workaround to this issue?
First of all, thanks for the steps to reproduce! Though they're not working with the current webpack.
There are also a few changes in packaging since 7.1.1 (and currently even Rollup outputs warning related to this), the current output is:
$ npm i rollup @rollup/plugin-commonjs @rollup/plugin-node-resolve turndown webpack webpack-cli
added 151 packages, and audited 152 packages in 5s
[...]
$ echo 'console.log(require("turndown"))' > src.js
$ node src.js
[Function: TurndownService]
$ npx rollup src.js -p node-resolve -p commonjs -f cjs -o out.js
src.js → out.js...
(!) Entry module "src.js" is implicitly using "default" export mode, which means for CommonJS output that its default export is assigned to "module.exports". For many tools, such CommonJS output will not be interchangeable with the original ES module. If this is intended, explicitly set "output.exports" to either "auto" or "default", otherwise you might want to consider changing the signature of "src.js" to use named exports only.
https://rollupjs.org/guide/en/#outputexports
src.js
created out.js in 157ms
$ node out.js
{ default: [Getter] }
$ npx webpack -d
[webpack-cli] Error: Option '-d, --devtool <value>' argument missing
[webpack-cli] Run 'webpack --help' to see available commands and options
Would you mind looking into the issue again and suggest updated options to solve it if the problem persist?
Your output demonstrates that the problem persists with Rollup. (The warning from rollup src.js
is about the exports of src.js
, which don’t matter in this example. It can be appeased with either --exports=named
or --exports=default
with no other effect. The problem is in Turndown’s Rollup configuration, not mine.)
For webpack-cli@4, replace -d
with --mode=development --target=node
.