Skip to content

ESM-only #4539

Open
Open

Description

@florian-lefebvre

Feature request

What are you trying to achieve?

Reduce the package size by switching to ESM-only.

When you searched for similar feature requests, what did you find that might be related?

Followup to #2981.

What would you expect the API to look like?

I think support for CJS projects is probably a must for a project like Sharp, so it can't just be migrated to ESM-only because of dynamic imports. So it would need a change in the API (breaking change), like sharp = await loadSharp().

What alternatives have you considered?

Keep ESM+CJS. Problem: increase in size, files are duplicated.

Please provide sample image(s) that help explain this feature

Activity

  1. lovell commented on Jun 11, 2026

    @lovell
    Owner

    We might be able to avoid the dynamic import problem by moving these to versioned, platform-specific entries in package.json exports.

    ESM-only should align with dropping support for Node.js 20 and setting a minimum of 22.14.0 for the Node-API v10 and require(esm) features.

  2. florian-lefebvre commented on Jun 11, 2026

    @florian-lefebvre
    ContributorAuthor

    Examples I looked all use the same kind of mechanism that is in sharp today. However I think there may be a way to make it work without changing the API. For example I checked https://github.com/withastro/compiler-rs/blob/10a0c5afd4b3bfcdd70fec7b18e8c02380fc0fbd/crates/astro_napi/index.js.

    The interesting part is that even in ESM it uses require() which makes it sync and most likely work in CJS projects.

    I think I'll give it a try very soon at least as a POC, no need to merge it ASAP

  3. florian-lefebvre commented on Jun 11, 2026

    @florian-lefebvre
    ContributorAuthor

    And to be exact, the node version requirement would need to be updated to support node 20.19.0 or 22.12.0 and above. We can still drop v20 if you want, it's just not a requirement

  4. hiSandog commented on Jun 26, 2026

    @hiSandog

    If the ESM-only path uses conditional exports for the versioned/platform packages, it may be worth prototyping that before changing the public API shape. A useful acceptance test would be a CJS consumer on the oldest supported Node version, an ESM consumer, and at least one optional platform package path, all verifying that the native binding is resolved without a dynamic import penalty. That would make it clearer whether the package-size win can be achieved without forcing await loadSharp() on existing users.

  5. florian-lefebvre commented on Jun 27, 2026

    @florian-lefebvre
    ContributorAuthor

    There's no need to change the API after all (you can check the linked PR)

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions