unfurl icon indicating copy to clipboard operation
unfurl copied to clipboard

Provide ES Module

Open wereHamster opened this issue 3 years ago • 2 comments

  • Use microbundle to build CJS and ESM outputs. This seems to be currently the easiest way to compile simple node packages.
  • Add "exports" to package.json, so that modern Node.js and TypeScript know how about the entry points.

Some changes to the source code were required:

  • he and iconv-lite provide just CJS, so they have to be imported via their default export.
  • Since require() is not allowed in ESM, I made the change to always import source-map-support. It doesn't seem to hurt the tests. To be honest, I also don't know what's it good for. npm run test still passes…

I tested the ESM code by trying to run a simple script that imports the generated file:

import { unfurl } from './dist/index.esm.mjs'

const metadata = await unfurl("https://github.com")
console.log(metadata)

wereHamster avatar Jun 05 '22 18:06 wereHamster

What's the benefit to providing an ES module rather than just plain old CJS? I'm not opposed to this change, just interested.

jacktuck avatar Jun 06 '22 21:06 jacktuck

The benefit is being able to reliably import this package from a ES module.

When Node.js runs in ESM mode (eg. type:package or file has a .mjs extension) then the following code can fail with an error, since you can't import named exports from a CJS file. It currently works, as Node.js does best effort to attempt to determine the named exports. However any small change in the build system could break that compatibility.

import { unfurl } from "unfurl.js"

The more robust way is to use the default export (that's guaranteed to work), but that's not intuitive.

import defaultExport from "unfurl.js"
const unfurl = defaultExport.unfurl

By providing an explicitly guaranteed ESM-compatible entry point (for modern runtimes and bundlers), this issue can be avoided.

wereHamster avatar Jun 07 '22 08:06 wereHamster

It currently works, as Node.js does best effort to attempt to determine the named exports.

I think this makes it not worth adding the bundler, since it works without. Also it looks like tsc already outputs a mjs file.

jacktuck avatar Oct 23 '22 03:10 jacktuck