question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Publish CJS and ES transpiled files in different versions

See original GitHub issue

Is your feature request related to a problem? Please describe.

Each modular package on npm ships with both CJS and ES transpiles files.

$ npm install @aws-sdk/client-s3

$ du -sh node_modules/@aws-sdk/client-s3 
6.1M    node_modules/@aws-sdk/client-s3

$ du -sh node_modules/@aws-sdk/client-s3/dist-cjs
1.6M    node_modules/@aws-sdk/client-s3/dist-cjs

$ du -sh node_modules/@aws-sdk/client-s3/dist-es 
1.3M    node_modules/@aws-sdk/client-s3/dist-es

$ cat node_modules/@aws-sdk/client-s3/package.json| grep '"main"'
  "main": "./dist-cjs/index.js",

$ cat node_modules/@aws-sdk/client-s3/package.json| grep '"module"'
  "module": "./dist-es/index.js",

Since dist-cjs is used in Node.js and dist-es is consumed by browser, they can be shipped into two different packages/versions.

Describe the solution you’d like

Ship browser and Node.js versions in different package names (say with suffix -node and -browser)

This suggestion was followed in preview versions of AWS SDK for JavaScript (v3). For example: @aws-sdk/client-s3-node

It was discontinued primarily because it’s not scalable.

  • It generates duplicate code which needs to be maintained in repository.
  • Supporting new environment (say ReactNative) would require adding new package per client (say with suffix -rn).
  • Supporting new module module system (say ESM) would require adding new package per client (say node-esm)

Ship different dist in prerelease tags

This suggestion includes using prerelease tags for shipping specific versions where reducing npm install size is important. For example:

  • Ship all dist-* in version X.Y.Z
  • Ship only dist-node-cjs in version X.Y.Z-node-cjs
  • Ship only dist-node-esm in version X.Y.Z-node-esm
  • Ship only dist-node-types in version X.Y.Z-node-types

The separate tags are not required for browser and react-native environments, as they are expected to use bundlers and are not dependent on npm install size.

In environments where npm install size is not a concern, developers can use X.Y.Z version as follows:

// package.json
{
  "dependencies": {
    //...
    "@aws-sdk/client-s3": "X.Y.Z",
    //...
  }
}

In environments where npm install size is a concern (while using ESM on Node.js), developers can use X.Y.Z-node-esm version as follows:

// package.json
{
  "dependencies": {
    //...
    "@aws-sdk/client-s3": "X.Y.Z-node-esm",
    //...
  }
}

For developers requiring types for while using prerelease versions, then can just add X.Y.Z-node-esm in devDependencies as follows:

// package.json
{
  "dependencies": {
    //...
    "@aws-sdk/client-s3": "X.Y.Z-node-esm",
    //...
  },
  "devDependencies": {
    //...
    "@aws-sdk/client-s3": "X.Y.Z-types",
    //...
  }
}

The different versions will be managed in the repo by creating custom package.json files for each prerelease tag, similar to how it’s done in tsconfig. The release script will use custom package.json when publishing packages on npm.

  • package.json: will include all configurations.
  • package.node.cjs.json: will include configurations and dependencies only for CommonJS.
  • package.node.esm.json: will include configurations and dependencies only for ESM.
  • package.types.json: will include configurations and dependencies only for types.

Describe alternatives you’ve considered

Scrapping of dist-* folders which are not being used in postinstall script.

Additional context

Request proposed earlier in:

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:1
  • Comments:8 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
trivikrcommented, Oct 13, 2022

Revisiting. We only need Node.js specific variant to reduce install size. The browser specific variant is not needed, as most users use bundlers.

1reaction
trivikrcommented, Jan 25, 2022

Revisiting this idea: looking at semver 2.0 specifications, it would be more helpful to use build metadata instead of prerelease tags.

For example:

  • Ship all dist-* in version X.Y.Z
  • Ship only dist-node-cjs in version X.Y.Z+node-cjs
  • Ship only dist-node-esm in version X.Y.Z+node-esm
  • Ship only dist-node-types in version X.Y.Z+node-types
Read more comments on GitHub >

github_iconTop Results From Across the Web

Publish ESM and CJS in a single package - Anthony Fu
A short tutorial of shipping both ESM and CJS dual formats in a single NPM package.
Read more >
Publishing NPM Packages as Native ES Modules - Medium
Node.js has had native support for ES modules since version 14, here's why you should (probably) be using it, how to migrate, and...
Read more >
How to transpile ES modules with webpack and Node.js
Learn how webpack interacts with and supports ES modules in this deep dive tutorial on transpilation in Node.js.
Read more >
How can I publish an NPM module with both commonjs and ...
You can use a bundler like webpack or rollup in combination with babel . They provide options to compile to multiple targets.
Read more >
How to Create a Hybrid NPM Module for ESM and CommonJS.
These defaults can be overridden by explicitly naming a file with a .cjs or .mjs extension. package.json: { "version": "1.2 ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found