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.

Improve ESM exports and enable tree shaking

See original GitHub issue

I identified several areas where we could improve the way Ethers gets exported. Please let me know what you think, and if / how I can help with these 🤗

Marking modules as side-effect free

This might be the easiest improvement: assuming all the Ethers packages are side effect free, marking them as such would make it possible for bundlers to eliminate the imports that are not used.

Note: I tried to do it and run build-all and it seems to impact something in the build configuration: the BN export of bn.js (which is is CJS) doesn’t seem to get converted properly anymore.

Code splitting

The easiest way to eliminate code is to provide exports in ES modules and separate every module in its own file. __PURE__ annotations can help too, but their support varies a lot from a bundler to another. It makes them adapted as an additional optimization, but they don’t really work as a primary way to enable tree shaking.

At the moment, the entire library is bundled in a single file. For the ESM export, setting the output.preserveModules to true and exporting everything into a dist/esm directory would probably be enough.

The package.json browser field

The browser field takes precedence over module and main in some bundlers configured to export for browsers. A consequence of it is that it makes it impossible to use the ESM export of Ethers. Is this field needed at all? Browser support for ES modules is excellent now (with the exception of IE 11 which is close to reach end of life), and most people use a bundler nowadays.

This field could then be useful to provide browser versions of modules (CJS or ESM) that are meant to be used in Node.js environments (see https://github.com/defunctzombie/package-browser-field-spec#replace-specific-files---advanced), rather than using it as an alternative to main and module. It could also provide to browsers the same structure than the module export, but minified. It would make import … from "//unpkg.com/ethers" provide an optimized build which could be super nice 😃

The ethers named export

Ethers exports the ethers object, which contains all the other named exports. Even though a __PURE__ annotation is being used, it might be difficult for some bundlers to respect it and might prevent any code elimination to happen.

A solution could be to stop exporting this object, and update the documentation to suggest using import * as ethers from 'ethers' instead − while also explaining why individual exports should be preferred. Most bundlers will also accept import ethers from 'ethers' since trying to import a default export from a module not having one is usually converted into import * as … instead.

We could also decide to keep the ethers export. In that case, a solution would be to have it in a separate file (so that apps not using it could tree shake the library), and let users know in the documentation that it is not optimal.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:8
  • Comments:15 (13 by maintainers)

github_iconTop GitHub Comments

4reactions
ricmoocommented, Sep 23, 2020

As an FYI, I have been overhauling the build scripts the last week or so and plan to address this over the next few weeks.

1reaction
ricmoocommented, Nov 22, 2020

@csmartinsfct I’ve investigated a bit, and ethers is not designed to have folders below the root imported from directly. Your code above is actually pulling the non-ESM version in, but I tried pulling in the ESM version directly, and it doesn’t do much better (I thought it might handle it, but tree-shaking is still in its infancy).

I may pull the utils out and make it its own sub-modules to help improve these cases, but the better solution for you is probably to add @ethersproject/units to your package.json and install that, then do the import { formatEther } from "@ethersproject/units" directly.

Let me know if that works for you.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Tree Shaking - webpack
Tree shaking is a term commonly used in the JavaScript context for dead-code elimination. It relies on the static structure of ES2015 module...
Read more >
Tree-Shaking: A Reference Guide - Smashing Magazine
Tree -shaking” is a must-have performance optimization when bundling JavaScript. In this article, we dive deeper on how exactly it works and ...
Read more >
Reduce JavaScript payloads with tree shaking - web.dev
Tree shaking is a form of dead code elimination. The term was popularized by Rollup, but the concept of dead code elimination has...
Read more >
Tree shaking and code splitting in webpack - LogRocket Blog
Here, we'll explain tree shaking and code splitting in webpack and discuss how to combine them for the most optimal bundle possible.
Read more >
How To Make Tree Shakeable Libraries - Theodo blog
Tree shaking is a term commonly used within a JavaScript context to describe the removal of dead code. It relies on the import...
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