Refine package exports
ggrossetie opened this issue · 3 comments
We should refine exports as described in: https://nodejs.org/api/packages.html#packages_package_entry_points
Currently, we define the following:
{
"type": "module"
"main": "dist/node/asciidoctor.js",
"browser": "dist/browser/asciidoctor.js",
"module": "dist/browser/asciidoctor.js",
}
This is not good enough because web bundlers prioritize module
when the target is node
.
As a result, we need to
{
"type": "module"
"main": "dist/node/asciidoctor.cjs",
"browser": "dist/browser/asciidoctor.umd.js",
"module": "dist/browser/asciidoctor.module.js",
"exports": {
".": {
"node": {
"import": "./dist/node/asciidoctor.js",
"require": "./dist/node/asciidoctor.cjs",
"default": "./dist/node/asciidoctor.cjs"
},
"browser": "./dist/browser/asciidoctor.umd.js",
"umd": "./dist/browser/asciidoctor.umd.js",
"import": "./dist/browser/asciidoctor.module.js",
"default": "dist/browser/asciidoctor.umd.js"
}
}
}
Open questions:
- Should we support
unpkg
(aliasumd:main
)? https://github.com/developit/microbundle#-installation--setup-- - Should we minify browser files?
- Should we use
development
/production
in order to provide unminified files in development and minified files in production? - According to: https://webpack.js.org/guides/package-exports/#providing-different-versions-depending-on-target-environment we might need to configure
module
in theexports
in addition toimport
?
As you can see, the above definition prioritize the browser. I think this is safer since exports
is not broadly supported by web bundlers (which most of the time target the browser).
I'm still thinking about whether or not we should export an UMD. If we don't, it would greatly simplify things on our side and I believe that most (all?) web bundlers can now work with an ESM library.
Without UMD:
{
"type": "module"
"main": "dist/node/asciidoctor.cjs",
"browser": "dist/browser/asciidoctor.js",
"module": "dist/browser/asciidoctor.js",
"exports": {
".": {
"node": {
"import": "./dist/node/asciidoctor.js",
"require": "./dist/node/asciidoctor.cjs",
"default": "./dist/node/asciidoctor.js"
},
"default": "dist/browser/asciidoctor.js"
}
}
}
"default" - the generic fallback that always matches. Can be a CommonJS or ES module file. This condition should always come last.
https://nodejs.org/api/packages.html#conditional-exports
Since default
is unspecified, it's probably better to use an ES module file (i.e., future proof).
It's arguably a bit misleading that main
points to a CommonJS module file since type
is module
but it's the recommended by the Node.js documentation:
If both "exports" and "main" are defined, the "exports" field takes precedence over "main". "exports" are not specific to ES modules or CommonJS; "main" is overridden by "exports" if it exists. As such "main" cannot be used as a fallback for CommonJS but it can be used as a fallback for legacy versions of Node.js that do not support the "exports" field.
Newer version of Node.js (which support ES module) will use exports.node.import
over main
.
I think we did a relatively good job in 3.0.4, closing.