GeistHaus
log in Β· sign up

https://e18e.dev/blog.rss

rss
19 posts
Polling state
Status active
Last polled May 19, 2026 00:44 UTC
Next poll May 19, 2026 21:32 UTC
Poll interval 86400s
ETag "adddd7f96b1c7e1a8dd6cfcccc9b5196-ssl-df"

Posts

replacements.fyi - A new module replacements website
Show full content
replacements.fyi - A new module replacements website ​

April 27, 2026

replacements.fyi cover image

replacements.fyi is live! πŸš€

It's a new, focused interface for exploring the e18e module replacements dataset - search any package and instantly see if there's a native equivalent or a community-recommended alternative.

What makes this launch worth writing about isn't just the site though - it's how it got built. From a Discord message to a live site in a couple of days, here's the story.

The idea ​

The module replacements project provides a community-defined list of npm packages and their recommended alternatives, whether that's replacing with native functionality, small code snippets, or other packages entirely.

This data is already used in various tools today, such as the e18e ESLint plugin, the e18e CLI and npmx.

However, there isn't a great way to explore this data in a more general way. The e18e site has a set of replacement docs, but these only cover a subset of the data as they only list documented replacements. All native and snippet replacements are missing from these docs.

The solution? Build a dedicated site for exploring this data! A place where you can search for packages to see if there are any replacements available, filter by runtime, and view the details of them.

The collaboration ​

Two weeks ago, I threw the idea out there in the e18e Discord and asked a few people what they thought about it. That same day, @paolo.ricciuti.me jumped on it and already had a basic svelte-powered site up and running by the end of the day! πŸ”₯

In the following days, @AlexanderKaran, Roman, and @dreyfus all joined in the fun and started working on the project with Paolo.

In the last week alone, there have been 26 merged PRs. All of this before we'd even officially announced the project, purely from chatter in the e18e Discord.

This kind of collaboration is always amazing to see. Just a great group of people who care about improving the ecosystem, coming together to build something useful for everyone.

replacements.fyi ​

The new replacements.fyi site is the result of this collaboration! πŸŽ‰

The aim of this site is to be a focused tool just like npmgraph and pkg-size. It doesn't need to do everything, but it should do one thing really well: make it easy to explore, discover, and understand module replacements.

At its core, the site is a simple search interface that allows you to look up any npm package and see if there are any recommended replacements for it.

The data gives us the ability to do more than this though. Unlocked by the work on the upcoming module replacements v3, we can expose filters that allow you to narrow down replacements by runtime. From the runtime itself, to the specific versions you're targeting - plus links to documentation and examples where available.

In a world driven largely by AI agents these days, we've also tried to make the site as agent-friendly as possible. Giving agents direct access to replacement advice means something like Claude can now produce code which leans more towards using native functionality than installing new dependencies.

Prior art: npmx ​

The npmx site already exposes much of this data when viewing a package. For example, if you view chalk on npmx, you will see a notice telling you that Node natively supports styleText for terminal colours these days.

npmx chalk screenshot

This has greatly improved the visibility of replacements, and has already led to many clean up PRs throughout the ecosystem.

If you want to see more than the replacements of a package, npmx is still a great place to go. In addition to the replacement info, the e18e community has also collaborated with npmx on displaying things like package size changes, security notices, and more.

Future plans ​

Now that we have the basics sorted, there are a few improvements and features we want to add in the future:

  • Ability to set a preferred runtime version (e.g. Node 20.x) to filter out replacements that require newer versions
  • Ability to view a package's replaceable dependencies (defer to npmx for a deeper dive into the package graph)
  • Improved integration with agentic tools
Get involved ​

If you want to help out, join the discord. We will be opening issues for these things and more, so all help is very much welcome and appreciated. Even if you just want to give feedback on the site, or suggest a replacement, that would be amazing!

https://e18e.dev/blog/replacements-fyi-launch.html
Collaborating with npmx
Show full content
Collaborating with npmx ​

March 3, 2026

As part of reaching more developers with best practice advice and tools, we have recently started collaborating with the great new npmx project!

What is npmx? ​

Today, the npm website is lacking in many useful features and seems to largely be unmaintained other than for bug fixes. This has led to an increase in demand for an alternative frontend to the npm registry.

Many people have been trying to solve this problem for some time now. For example, @bluwy created a very helpful user script which adds a bunch of extra features to the npm website at runtime. However, this has its limits as a user script. Similarly, many people have tried to create alternative frontends, but each with their own approach and none have really taken off.

npmx is a new project which aims to solve this problem, and has done much of that by bringing all of these people and many more together to collaborate on one unified frontend.

How we're collaborating ​

A large part of the e18e initiative is about documenting and advising developers on how to make their packages more performant. We do this today through a few of our tools: an ESLint plugin, a CLI, and a GitHub action.

These are all extremely useful tools, but they need to be introduced into your workflow rather than being available out of the box.

As an npm frontend, npmx is the perfect place to surface this advice and tooling to developers at the point of discovery. For example, when a developer is looking at a package on npmx, they could see a warning that the package has a large footprint and be given advice on how to fix it, along with links to our tools to help them do that.

Performance advice on npmx ​

The community have already added some great features to npmx which make use of our curated best practices advice.

For example, when looking at a package which is known to be redundant across all modern engines, you will now see something like this:

npmx screenshot

Similarly, when you look at a package which has significantly increased in size or dependencies since the last version, you will see something like this:

npmx screenshot

Lastly, when you look at the dependencies of a package, you will now see warnings on any dependencies which are known to be redundant or have more performant replacements:

npmx screenshot

What's next? ​

This is just the beginning of our collaboration and what we can achieve together. A few more upcoming ideas we have include:

  • Adding smart dependency advice (based on your chosen minimum Node version, browser support, etc.)
  • Adding richer advice with example code snippets and links to our tools
  • Highlighting packages with duplicate dependencies

Thanks to our community-maintained replacements data, much of this advice and more is already available to be surfaced.

In addition to the module replacements data, we are also hard at work on a new data project which will provide enriched registry data. This will allow npmx and other tools to show things like license information, install sizes, and more.

Get involved ​

If you're interested in collaborating with us on this, or have any ideas on how we can improve the experience for developers, please join our community on Discord and let us know!

https://e18e.dev/blog/npmx-collaboration.html
The Year Ahead (2026)
The Year Ahead (2026) ​

January 24, 2026

October Contributions Cover Image

We haven't had a blog post in a while, largely due to the holiday season but also because many of us have been hard at work on some fairly chunky e18e projects lately! So let's have a look ahead at what's coming in 2026 and a small recap on what we got up to last year πŸš€

2025 Recap ​

In 2025, we saw a great number of contributions, new projects, and milestones across the e18e ecosystem.

New Projects ​ Notable Wins ​ Milestones ​
  • tinyglobby reached 62M weekly downloads
  • tinyexec reached 36M weekly downloads
  • knip reached 6M weekly downloads
  • obug reached 6.7M weekly downloads
  • modern-tar reached 309K weekly downloads
Sponsored by Google Chrome πŸš€ ​

A huge milestone this week: the Google Chrome team have officially sponsored us as part of their Chrome Performance fund! πŸŽ‰

The e18e community and the Chrome team share a lot of the same goals - improving web performance and modernizing the code we ship to users on the web. So it is great to have their support and be able to collaborate more closely.

They have been very active as part of the WebDX community group, a w3c group which aims to improve developer experience on the web. Two notable projects from this group will be fundamental for much of the tooling we're building in e18e - baseline, and the web-features project.

As part of the next major version of the module-replacements data set, we will be integrating both baseline and web-features. These will allow us to make much smarter suggestions based on the target environments of a project, as well as being able to suggest syntax and API replacements based on feature support.

This support is very much appreciated and will go a long way to helping us improve performance across the entire ecosystem πŸ™

Project Leads ​

Though much of what the e18e community does is through contributions, we do also have a lot of ongoing and upcoming projects. Most of these are around building developer tooling to help make performance a more central part of the development workflow.

To help manage these projects and share the load, we've recently introduced a few project leads. These are some great people who were already part of the community and have stepped up to help drive these projects forward.

Current leads:

e18e & Friends ​

@thealexlichter has been a long-time member of the e18e community, and is now the host of our new show: e18e & Friends!

Every month, we will invite a guest from the wider community to chat about what they've been working on, often with a focus on the performance space.

This will be live streamed so we can take questions from the audience, and recorded for later viewing on YouTube.

The first episode will be live on the 10th February, and the guest is yet to be announced!

Follow along on Discord for updates πŸš€

Module Replacements v3 ​

The module replacements project has been core to the e18e community since the beginning. It provides a data set which maps older, heavier dependencies to modern, more performant alternatives.

This has done a great job so far, but has been lacking a few notable things:

  • Representing syntax replacements (e.g. replacing some loops with for...of)
  • Representing API replacements (e.g. replacing array[array.length - 1] with array.at(-1))
  • Representing engine constraints (e.g. only suggest this replacement if the project supports Node 16+)

All of these are limitations of the schema we use, in that we simply don't have a place in the data to hold this information.

The next version of this data set will introduce a new schema which supports all of these use cases, and more!

This will lead to us being able to make smarter suggestions in tools like the ESLint plugin, based on baseline and engine constraints rather than just a flat list of recommendations.

Replacements GitHub action ​

We're in the very early design stages, but we're cooking up a GitHub action which will automatically create pull requests for module replacements and syntax improvements!

This action should do a lot of what the CLI and the ESLint plugin do, but in an automated fashion and focused around migrations rather than analysis.

Think of it as dependabot for modernization and performance improvements!

Framework Performance ​

The framework performance tracker is an exciting new project we've had brewing for a while now. A website which tracks various useful performance metrics across popular web meta-frameworks like Nuxt, Astro, and SvelteKit.

Comparing these frameworks is a complex task, as they all do things very differently and each framework has its own strengths it prioritizes in its own documented metrics. By creating this tracker, we hope to provide a more objective view of how they perform across the board.

To start, we're going to focus on a set of core metrics rather than comparisons, with the goal of expanding this over time. For example, node_modules size and build times might look something like this (with imaginary data):

| Framework | node_modules Size | Build Time | |

Show full content
The Year Ahead (2026) ​

January 24, 2026

October Contributions Cover Image

We haven't had a blog post in a while, largely due to the holiday season but also because many of us have been hard at work on some fairly chunky e18e projects lately! So let's have a look ahead at what's coming in 2026 and a small recap on what we got up to last year πŸš€

2025 Recap ​

In 2025, we saw a great number of contributions, new projects, and milestones across the e18e ecosystem.

New Projects ​ Notable Wins ​ Milestones ​
  • tinyglobby reached 62M weekly downloads
  • tinyexec reached 36M weekly downloads
  • knip reached 6M weekly downloads
  • obug reached 6.7M weekly downloads
  • modern-tar reached 309K weekly downloads
Sponsored by Google Chrome πŸš€ ​

A huge milestone this week: the Google Chrome team have officially sponsored us as part of their Chrome Performance fund! πŸŽ‰

The e18e community and the Chrome team share a lot of the same goals - improving web performance and modernizing the code we ship to users on the web. So it is great to have their support and be able to collaborate more closely.

They have been very active as part of the WebDX community group, a w3c group which aims to improve developer experience on the web. Two notable projects from this group will be fundamental for much of the tooling we're building in e18e - baseline, and the web-features project.

As part of the next major version of the module-replacements data set, we will be integrating both baseline and web-features. These will allow us to make much smarter suggestions based on the target environments of a project, as well as being able to suggest syntax and API replacements based on feature support.

This support is very much appreciated and will go a long way to helping us improve performance across the entire ecosystem πŸ™

Project Leads ​

Though much of what the e18e community does is through contributions, we do also have a lot of ongoing and upcoming projects. Most of these are around building developer tooling to help make performance a more central part of the development workflow.

To help manage these projects and share the load, we've recently introduced a few project leads. These are some great people who were already part of the community and have stepped up to help drive these projects forward.

Current leads:

e18e & Friends ​

@thealexlichter has been a long-time member of the e18e community, and is now the host of our new show: e18e & Friends!

Every month, we will invite a guest from the wider community to chat about what they've been working on, often with a focus on the performance space.

This will be live streamed so we can take questions from the audience, and recorded for later viewing on YouTube.

The first episode will be live on the 10th February, and the guest is yet to be announced!

Follow along on Discord for updates πŸš€

Module Replacements v3 ​

The module replacements project has been core to the e18e community since the beginning. It provides a data set which maps older, heavier dependencies to modern, more performant alternatives.

This has done a great job so far, but has been lacking a few notable things:

  • Representing syntax replacements (e.g. replacing some loops with for...of)
  • Representing API replacements (e.g. replacing array[array.length - 1] with array.at(-1))
  • Representing engine constraints (e.g. only suggest this replacement if the project supports Node 16+)

All of these are limitations of the schema we use, in that we simply don't have a place in the data to hold this information.

The next version of this data set will introduce a new schema which supports all of these use cases, and more!

This will lead to us being able to make smarter suggestions in tools like the ESLint plugin, based on baseline and engine constraints rather than just a flat list of recommendations.

Replacements GitHub action ​

We're in the very early design stages, but we're cooking up a GitHub action which will automatically create pull requests for module replacements and syntax improvements!

This action should do a lot of what the CLI and the ESLint plugin do, but in an automated fashion and focused around migrations rather than analysis.

Think of it as dependabot for modernization and performance improvements!

Framework Performance ​

The framework performance tracker is an exciting new project we've had brewing for a while now. A website which tracks various useful performance metrics across popular web meta-frameworks like Nuxt, Astro, and SvelteKit.

Comparing these frameworks is a complex task, as they all do things very differently and each framework has its own strengths it prioritizes in its own documented metrics. By creating this tracker, we hope to provide a more objective view of how they perform across the board.

To start, we're going to focus on a set of core metrics rather than comparisons, with the goal of expanding this over time. For example, node_modules size and build times might look something like this (with imaginary data):

Framework node_modules Size Build Time Framework A 45 MB 1.2s Framework B 287 MB 3.1s Framework C 112 MB 1.8s

Many of these metrics should then be helpful for teams when choosing a framework, as well as tracking how each framework improves over time.

This is a large project; there's a lot to track and comparing fairly across frameworks isn't trivial. But if we pull it off, it'll be a genuinely useful resource for seeing how frameworks evolve in the performance space over time.

e18e CLI ​

The e18e CLI has had a bumpy start while we figured out the scope and the right developer experience. Though we've had a few delays, we are now well on our way to a stable release!

Ultimately, it will focus on these areas:

  • Dependency analysis
  • Security analysis (e.g. trust levels)
  • Replacement suggestions
  • Replacement migrations

This and the ESLint plugin will achieve roughly the same goals - allowing you to choose the one you prefer based on your workflow.

More to come on this front soon πŸš€

Runtime analysis ​

This one isn't well defined yet, but is something we've been discussing on and off for a while now - a way to analyze the runtime code of a given web app for redundant polyfills, legacy code, and other improvable areas.

It is a fairly difficult problem to solve, but would allow us to give suggestions outside of developer workflows, and reach a wider audience.

Especially for helping reduce reliance on redundant polyfills, this could be a very useful tool.

Get involved ​

If you want to help out, join the discord. We'd love to have the help πŸ™

https://e18e.dev/blog/the-year-ahead-2026.html
e18e & Friends: Community Show
Show full content

January 23, 2026

e18e & friends ​

We're starting a new community show: e18e & Friends!

What is e18e & Friends? ​

e18e & Friends is a new live streamed show where we catch up with friends from around the JavaScript ecosystem. Often people working on performance and modernization projects, but really anyone who has something interesting to share!

The e18e community has so many amazing people from all corners of the JavaScript ecosystem. Library authors, contributors, engine implementors, framework maintainers, and many more. We'd love to bring some of these folks together and provide a platform to share their work more widely.

Introducing the host... ​

As the host, we're super excited to have @TheAlexLichter on board!

Alex has been a long time advocate for performance in the JavaScript ecosystem. As part of the VoidZero team, he's also been hard at work pushing web tooling forward with projects like Rolldown.

He's also done some great talks and has hosted the DejaVue podcast for some time now, so we're really excited to have him leading the show.

The format ​

Each episode will focus around a guest from the community who will share some of the exciting work they're doing, or just have a chat about performance with us in general.

There will be a small segment where we catch up on what's new in the ecosystem, and what the e18e community has been up to this month.

We'll also spend some time answering questions from the audience, so make sure to tune in live if you can!

Join us live! ​

If you'd like to join us live for the first episode of e18e & Friends, you can find the event on Discord. We will be streaming on February 10th, 2026 at 7pm CET.

https://e18e.dev/blog/e18e-and-friends.html
tinyglobby: a success story in modernization and performance

November 11, 2025

tinyglobby: a success story in modernization and performance)

Author: Madeline GurriarΓ‘n (@superchupu)

My story with dependencies is odd. I started coding in JavaScript about six years ago, and over time I started to notice just how big my lockfiles were getting every time I wanted to use a new library. Most subdependencies didn't even seem related to the libraries I was using. I had a low-end laptop until recently, and every time this happened I'd notice just how slow installations were getting.

I started inspecting what subdependencies were being added to my projects, and whether or not they really were necessary in the modern days of the JavaScript ecosystem. After months of occasionally improving the dependency count of some libraries I was using, I found out about e18e right as it was made public, a place where I learned many ways I'd never thought of to improve libraries.

One notable library I wanted to replace was globby in tsup, and I got recommended to try fdir and picomatch for it. I submitted a PR, which got merged after a few days. The next day I woke up to users being unable to use tsup because of it. It turns out that globs are complex! I would have never thought I'd spend the rest of the year working on globs.

Since some people from e18e were also stuck on lightweight globs, we decided it was best if my little tsup PR of less than 100 lines would be turned into its own library, so that others could benefit from its small size.

Dependency savings ​

Let's take a look at some comparisons with other libraries in this space:

Having fewer packages reduces the need to have as many people with access to merge and release new versions thus reducing supply chain vulnerabilities, of which we've seen a number of in the npm ecosystem. For example, just recently, users of glob, which has 26 dependencies, were affected by a supply chain attack in which a dependency - strip-ansi - was compromised. Users of tinyglobby would not have been affected by this particular attack and face far less risk of similar attacks in the future.

High adoption enables deduplication ​

Of course, globby and fast-glob are widely used, so you may question whether switching to tinyglobby just results in more dependencies rather than any savings once dependency deduplication is factored in.

Fortunately, the community has been hard at work consolidating around the use of tinyglobby and reducing this problem.

A whole raft of popular build tools now rely solely on tinyglobby for glob functionality:

  • Vite
  • SWC
  • copy-webpack-plugin
  • tsup
  • tsdown
  • unbuild
  • nx
  • lerna
  • and many more...

None of these tools have a deep dependency on other glob libraries - all of them use tinyglobby all the way down πŸŽ‰

Similarly, many popular frameworks have made the same move:

  • React Router
  • Preact
  • Angular
  • SvelteKit
  • Astro
  • Starlight
  • Eleventy

New apps using these frameworks will no longer have deep dependencies on multiple glob libraries.

For others like Nuxt, SolidStart, and TanStack Start, all dependencies have fully switched to tinyglobby and those frameworks will only use tinyglobby once they update their dependencies. Most remaining frameworks use both tinyglobby and fast-glob.

Some ecosystems now rely almost entirely on tinyglobby β€” Svelte maintainer benmccann has switched over most of the Svelte ecosystem to using tinyglobby. Once the pending PR to typescript-eslint is merged, you will be able to setup a new SvelteKit project with every integration it offers and your project will exclusively use tinyglobby. Many other notable projects such as pnpm, node-gyp, and eslint-import-resolver-typescript have made the switch as well.

For projects that are new or have recently updated dependencies, tinyglobby is more likely to be used than fast-glob or globby. On both a relative and absolute basis, tinyglobby usage is growing faster than alternatives. Something important to keep in mind here is that all usage of tinyglobby is on a single release line where as it's split across major versions for alternatives. E.g. globby usage is split across ten versions (v5-14 all have more than 1m downloads/week). This means that the rate at which tinyglobby is being used on new projects compared to alternatives is even higher than raw download numbers might indicate.

Performance ​

The journey with tinyglobby started out focusing more on size rather than performance. After many months past its initial release though, I am proud to say that it is not only smaller but also faster than alternatives for the vast majority of use cases.

A few months ago, an important performance improvement was achieved that applied to every use case that didn't glob outside the cwd used. Comparing benchmarks between the newest release and the previous one shows a considerable speedup! Here's one where tinyglobby didn't use to be the fastest - globbing packages/*.tsconfig.json in the typescript-eslint repository:

| | ops/s | |

Show full content

November 11, 2025

tinyglobby: a success story in modernization and performance)

Author: Madeline GurriarΓ‘n (@superchupu)

My story with dependencies is odd. I started coding in JavaScript about six years ago, and over time I started to notice just how big my lockfiles were getting every time I wanted to use a new library. Most subdependencies didn't even seem related to the libraries I was using. I had a low-end laptop until recently, and every time this happened I'd notice just how slow installations were getting.

I started inspecting what subdependencies were being added to my projects, and whether or not they really were necessary in the modern days of the JavaScript ecosystem. After months of occasionally improving the dependency count of some libraries I was using, I found out about e18e right as it was made public, a place where I learned many ways I'd never thought of to improve libraries.

One notable library I wanted to replace was globby in tsup, and I got recommended to try fdir and picomatch for it. I submitted a PR, which got merged after a few days. The next day I woke up to users being unable to use tsup because of it. It turns out that globs are complex! I would have never thought I'd spend the rest of the year working on globs.

Since some people from e18e were also stuck on lightweight globs, we decided it was best if my little tsup PR of less than 100 lines would be turned into its own library, so that others could benefit from its small size.

Dependency savings ​

Let's take a look at some comparisons with other libraries in this space:

Having fewer packages reduces the need to have as many people with access to merge and release new versions thus reducing supply chain vulnerabilities, of which we've seen a number of in the npm ecosystem. For example, just recently, users of glob, which has 26 dependencies, were affected by a supply chain attack in which a dependency - strip-ansi - was compromised. Users of tinyglobby would not have been affected by this particular attack and face far less risk of similar attacks in the future.

High adoption enables deduplication ​

Of course, globby and fast-glob are widely used, so you may question whether switching to tinyglobby just results in more dependencies rather than any savings once dependency deduplication is factored in.

Fortunately, the community has been hard at work consolidating around the use of tinyglobby and reducing this problem.

A whole raft of popular build tools now rely solely on tinyglobby for glob functionality:

  • Vite
  • SWC
  • copy-webpack-plugin
  • tsup
  • tsdown
  • unbuild
  • nx
  • lerna
  • and many more...

None of these tools have a deep dependency on other glob libraries - all of them use tinyglobby all the way down πŸŽ‰

Similarly, many popular frameworks have made the same move:

  • React Router
  • Preact
  • Angular
  • SvelteKit
  • Astro
  • Starlight
  • Eleventy

New apps using these frameworks will no longer have deep dependencies on multiple glob libraries.

For others like Nuxt, SolidStart, and TanStack Start, all dependencies have fully switched to tinyglobby and those frameworks will only use tinyglobby once they update their dependencies. Most remaining frameworks use both tinyglobby and fast-glob.

Some ecosystems now rely almost entirely on tinyglobby β€” Svelte maintainer benmccann has switched over most of the Svelte ecosystem to using tinyglobby. Once the pending PR to typescript-eslint is merged, you will be able to setup a new SvelteKit project with every integration it offers and your project will exclusively use tinyglobby. Many other notable projects such as pnpm, node-gyp, and eslint-import-resolver-typescript have made the switch as well.

For projects that are new or have recently updated dependencies, tinyglobby is more likely to be used than fast-glob or globby. On both a relative and absolute basis, tinyglobby usage is growing faster than alternatives. Something important to keep in mind here is that all usage of tinyglobby is on a single release line where as it's split across major versions for alternatives. E.g. globby usage is split across ten versions (v5-14 all have more than 1m downloads/week). This means that the rate at which tinyglobby is being used on new projects compared to alternatives is even higher than raw download numbers might indicate.

Performance ​

The journey with tinyglobby started out focusing more on size rather than performance. After many months past its initial release though, I am proud to say that it is not only smaller but also faster than alternatives for the vast majority of use cases.

A few months ago, an important performance improvement was achieved that applied to every use case that didn't glob outside the cwd used. Comparing benchmarks between the newest release and the previous one shows a considerable speedup! Here's one where tinyglobby didn't use to be the fastest - globbing packages/*.tsconfig.json in the typescript-eslint repository:

ops/s tinyglobby 0.2.15 2357 Β± 100 tinyglobby 0.2.14 981 Β± 131 fast-glob 1878 Β± 110 glob 1767 Β± 95 node:fs glob 941 Β± 74 Stability ​

tinyglobby is a newer library, so you may be wondering whether switching to it introduces a higher risk of undiscovered bugs or not. This is where tinyglobby is fortunate in that it has been able to take on learnings from those which came before it, including edge-cases and bugs.

In tinyglobby's earlier days, some users encountered regressions. Thankfully, the vast majority of issues were quick to be fixed. With such widespread adoption by high profile widely-used projects in the ecosystem, any bugs in tinyglobby are found and reported quickly.

On top of this, each fixed issue introduces an associated test and, as a result, tinyglobby has over 100 individual tests. These regression tests will help ensure no breaking changes occur in the future, too.

The few remaining behavior differences between tinyglobby and its alternatives are well-known and have been documented in the project's website, which aims to serve as a comprehensive guide and reference point.

When there has been a bug in tinyglobby, it's been relatively straightforward to identify whether it's in tinyglobby itself or one of its two dependencies. It can be much harder to track down an issue in a library with 17 dependencies or even to see all of the issues across all of the repos that might be present. In fact, fast-glob and its dependencies together have roughly twice as many open issues as tinyglobby and its dependencies combined.

tinyglobby has been very actively maintained and has the support of the e18e community who have been instrumental in identifying issues and their root causes. The biggest release so far, 0.2.15, has so far zero regressions reported despite it changing a lot of internals!

Standing on the shoulders of giants ​

tinyglobby depends on fdir and picomatch and would not be possible without them. I've learned a lot about the complexity of globbing over the past year and a half and it is wonderful being able to rely on picomatch as a battle-tested library implementing this functionality. And fdir lets us build on top of the fastest directory crawler on Node, which can easily crawl a directory containing 1 million files in < 1 second.

I'd also like to thank the authors of globby and fast-glob - Sindre Sorhus and Denis Malinochkin. tinyglobby is API-compatible with a subset of their APIs, which have found widespread adoption in the ecosystem. The creation of tinyglobby is in no way a criticism of their work. Those libraries implement a lot of functionality and are a great solution for many users!

tinyglobby is meant as a lightweight alternative for the vast majority of projects that don't need the full breadth of options provided by those libraries. Additionally, a special thanks should be given to Sindre for helping to push forward the ecosystem in ways that e18e is also working on. E.g. Sindre has converted many of his packages to be ESM-only. While this has made upgrades difficult for consumers in the past, all LTS versions of Node now support importing ESM code from CJS, which should greatly ease adoption of ESM-only packages.

https://e18e.dev/blog/tinyglobby-migration.html
Community Showcase (Q3 2025)
Show full content

October 31, 2025

Community Showcase (Q3 2025) ​

A little late, but here is the Q3 2025 community showcase! πŸŽ‰

The community have been producing some great things over the last few months, and improving even more projects. Here's just a few highlights of what we've been up to.

e18e GitHub Action ​

Recently, we saw the launch of the official e18e GitHub Action! This action allows you to easily check for dependency changes in your pull requests.

It applies various checks to determine if the dependency tree has changed in an unusual or notable way, helping to catch potential issues before they make it into your main branch.

Trust levels ​

The action detects when a dependency has changed its trust level. There are currently three trust levels:

  • Trusted: Published using OIDC (trusted publishing) with provenance
  • Provenance: Published with provenance, but not using OIDC
  • None: No provenance or OIDC

With the rise in supply chain attacks, it is important to be aware of if a package changes between these trust levels. The action will do this by flagging any decrease in trust level for a dependency.

Install size ​

This check will flag any pull request which increases the install size of your package overall.

The install size of a package is that of the node_modules directory after running an npm install. Significant increases are often a sign of bloat or unnecessary dependencies being added.

Bundle size ​

There also exists the ability to check for bundle size changes. This differs from install size as it is the size of the npm pack result (i.e. the tarball which would be published to npm).

This is extremely useful for libraries, as it can help catch accidental increases in bundle size which would affect end users.

Module replacements ​

Of course, this also plugs into e18e's existing module replacements, allowing you to enforce the use of more performant alternatives to certain packages.

If a pull request introduces a dependency which the community have marked as having suggested replacements, it will be flagged by the action.

What's next for the action? ​

This action is still evolving, and we plan on adding more checks in the future. If you have any ideas or feedback, please open an issue.

Module replacements ​

As part of a wider effort to improve documentation of e18e recommendations, the community have been hard at work adding the new module replacements docs!

These new docs provide migration guides and tips for each of the recommended replacements, making it super easy to switch.

Just a few examples:

Big thanks to @outslept for doing the majority of the work on this!

modern-tar and nanotar ​

While investigating ways to reduce install size and complexity, a commonly raised issue has been the use of the tar package, or the tar-fs package.

tar comes in at 1.8MB with 6 packages, while tar-fs is 3.6MB with 17 packages.

Both of these packages are rather large, and the community have been itching to replace them with something more lightweight for a while now.

That's where modern-tar and nanotar come in!

nanotar ​

nanotar is a super tiny runtime-agnostic implementation of parsing and creating tar files.

It comes in at just 37KB and 0 dependencies!

This comes from the unjs ecosystem, which has many more lightweight packages like this. Thanks to @pi0 for this one!

modern-tar ​

While nanotar is great for parsing and creating tar files, it doesn't currently have a way to extract them to the filesystem.

That's where modern-tar comes in!

modern-tar is can pack and unpack tar files to and from the filesystem, while still being very lightweight.

Similarly, it comes in at only 76KB and 0 dependencies πŸŽ‰

Really awesome work by @ayuhito here!

Immer ​

Delving into the speed up category, we've seen some great improvements to the popular immer library recently.

@acemarke has been hard at work doing deep dives into the CPU and memory performance of immer across the board. He has made an impressive number of optimizations, and is still going!

You can read all about it on the latest GitHub issue, where he details many of the changes made so far. Just a few highlights:

  • Improving iteration by avoiding Reflect and caching object shapes
  • Rewriting finalization to be callback based instead of recursive
  • Overriding array methods to avoid creating proxies on reads
  • Avoiding object spreads for shallow copies

These optimizations have led to some impressive speed-ups. For example, the latest branch is 20% faster than main on many benchmarks!

We also recently held our first community call, where we were lucky enough to have @acemarke walk us through these improvements and show us more of the deeper investigation.

Really great work here! πŸ™

Storybook ​

Storybook strikes again with another huge saving - migrating to ESM only!

They have announced Storybook v10 will be going ESM only. With this migration, they're able to drop all legacy CommonJS code from their published packages.

Storybook and many other popular packages currently ship two builds in their npm packages - one for CommonJS (CJS) and one for ESM. This means even if you install into an ESM-only project, you will still download the legacy CommonJS build, along with the duplicated type definitions.

By going ESM only, all of this falls away and there remains only one copy of everything.

This drops the storybook package from 66MB to 53MB, a great saving!

On top of this, even more savings were gained by resolving some tree-shaking issues. Big thanks to Bill for this one!

Netlify ​

Netlify have been collaborating with the e18e community for some time now, and putting great effort into improving the performance of their OSS packages.

Recently, we've seen two huge savings from them:

It's not often we get to see savings as crazy as these. The Netlify team have done an amazing job here.

Much of this saving comes from publishing two separate packages - one for development (with a bunch of dev-time tools, emulators, etc.), and one for production (just the runtime code).

This means production installs will run much faster, and the cost of the development tools is only paid when needed.

Upcoming projects ​ e18e CLI ​

The e18e CLI project missed a few milestones and isn't quite ready yet. However, with the completion and success of the GitHub Action, we're now in a much better place to complete the work.

This is core to the tooling the e18e community wants to provide, so we will be pushing hard to get this out soon!

Our vision for the CLI is that it can offer roughly the following:

  • Dependency tree analysis matching that of the GitHub action
  • Automated migrations to suggested replacements
  • Publish linting
  • Type definition linting

We are aiming to release an alpha version very soon, and will be reaching out to many of you to help test it out!

e18e MCP ​

We're also working on an e18e MCP server! This will allow us to offer module replacements as a data source to LLMs.

This is early stages but will hint to your chosen agent on which libraries to use and modern syntax to prefer.

The same capability should be available via the e18e CLI, leaving the choice of which you use up to you.

Module replacements v2 ​

Finally, we're working on the next version of the module replacements data πŸŽ‰

One of the goals of this is to allow us to support more engines other than Node, and to offer syntax-only replacements (e.g. new platform capabilities).

Once this is complete, our tooling should be able to more intelligently suggest replacements based on your project's target environment. If you use Bun, for example, it will prefer built-in Bun APIs over third-party alternatives.

Package publishing guide ​

In the wake of the recent supply chain attacks, many community members have been asking how to best secure their package publishing process.

To help with this, we've put together a package publishing guide which goes over best practices for securely publishing your packages.

In this guide, we cover how to configure a typical OIDC setup with GitHub Actions, as well as some best practices around keeping the workflow secure. We've also published a few different "recipes" to show how you can do the same with various changelog/release management tools.

This is the result of many discussions in the community, so a big thanks to everyone who contributed! Particularly, thanks to @sxzz, @dominikg, and @jviide for their help putting this together.

Community calls / stream ​

We had a small trial of a community call when @acemarke presented his immer optimizations. This was a great success, so we plan on doing more of these in the future!

Nothing is set in stone yet, but we're planning on doing a monthly community call, usually with a guest speaker from the community. Hopefully, this will give some good insight into what people are working on, and will help teach us all new things.

Keep an eye out for announcements in our Discord when the next one is scheduled.

Working Draft podcast ​

The Working Draft podcast also recently had an e18e-focused episode! You can check it out on their website (Note it is in German language).

Great work by @fuzzyma and @thealexlichter for representing the community so well.

We're always happy to see community members getting involved in advocating for better practices around performance like this. If you run a similar podcast or want to suggest one for us to appear on, please let us know in the Discord!

ViteConf ​

Earlier this month, the first in person ViteConf was held!

A few of us went along, and we even had the first e18e talk there πŸŽ‰

This was a great experience and so many people were interested in what the community has been up to. We'd love to make this more of a regular occurrence to help share the knowledge and increase collaboration.

From this event alone, we've kicked off a few collaborations with Astro, Netlify, Nuxt, and more!

This was also the first time a few of us were in person together. Just a few of the amazing people in our community who made the trip: @antfu, @bluwy, @fuzzyma, @pi0 πŸ₯³

Get involved ​

If you'd like to help out, come join our discord and say Hi!

https://e18e.dev/blog/community-showcase-q3.html
Community Showcase (Q2 2025)

July 18, 2025

Community Showcase (Q2 2025) ​

A little late, but it's time for another community showcase! πŸŽ‰

So many good things have happened over the last quarter in the community and around the ecosystem, and there's so much more to come πŸš€

Prettier CLI ​

The Prettier team has been collaborating with the e18e community for some time now on a new, faster CLI for Prettier. In June, this was released behind a flag for all to try out! πŸŽ‰

This has been a great collaboration, driven mostly by the work of @fabiospampinato and plenty of help from @fisker on the Prettier side of things.

You can see some of the huge performance improvements in the chart below:

prettier run time results

You can use this in your own project by using the new experimental flag:

sh
# via the CLI flag
prettier . --check --experimental-cli

# via an environment variable
PRETTIER_EXPERIMENTAL_CLI=1 prettier . --check

Without any other changes, this should speed up your formatting runs a whole lot πŸ™Œ

Read more about how we got here in the blog post.

e18e CLI ​

We posted about the upcoming e18e CLI some time ago and the rough idea behind it. Since then, the community has been hard at work building it and shaping the definition of what's to come.

Soon you will be able to do cool things like this:

sh
npx @e18e/cli migrate chalk # automatically migrate chalk to picocolors

npx @e18e/cli migrate --interactive chalk # interactively choose which library to migrate chalk to

npx @e18e/cli analyze # lint your dependency tree and produce useful stats

We now have the basics in place and a much fuller list of features to work towards. Just a few of the things this CLI will be able to do:

  • Automatic migrations to suggested replacements
  • Lint your dependency tree for common issues
  • Lint your publishing setup (with help from publint!)
  • Visualise CJS vs. ESM usage in your project
  • Bring your own codemods and replacements lists (so the CLI can migrate and detect migrations of your own internal dependencies)

We're also working towards having a GitHub automation which can create these migration PRs for you, and run the lint steps in your CI.

If you want to contribute or if you just want to test the CLI as we build it, we'd love the help. Come join us in the e18e Discord and join the #cli channel!

You can also follow along with the release roadmap in the roadmap issue.

Huge thanks to @paul, @passle and @fuzzyma for all the work so far.

Storybook 9 ​

Storybook recently released version 9! πŸš€

This release comes with all sorts of improvements like Storybook Test, story generation and much more. However, the highlight for us is by far the install footprint reduction and project complexity improvements.

Just look at this graphic taken from their post:

storybook 9 dependency graph

They've almost flattened their dependency tree! This is some great progress and the result of many months of work by the Storybook team - much of which involved collaborating with the e18e community.

You can read more about how they achieved this and how they're keeping on top of it in their blog post.

We also recently held a webinar where Jeppe from the Storybook team and James from e18e discussed the technical details behind these improvements. You can watch the recording on YouTube: Lessons learned from reducing bloat in Storybook where they dive deeper into the process and lessons learned.

Big thanks to the Storybook team for taking a lead on this kind of improvement, and for working so closely with the community throughout ❀️

ESM-only migration ​

Ever since require(esm) became a thing, we've been pushing to move more and more projects to ESM-only. Helping maintainers with the migration has been high up on our list, and we've made great progress.

On top of that, we're seeing a lot more migrations happening outside the community as more and more maintainers are choosing to follow suit.

Here's just a few projects we've seen migrated:

Some future migrations on the horizon too:

Thanks to @michael.faith for migrating some of these, and the maintainers who made the move themselves!

fdir ​

With help from @sxzz and @thealexlichter, fdir is now bundled using tsdown. This has lead to almost a 3x reduction in install size and a much faster build time for the maintainers!

This is unreleased as of writing, but will be coming soon. Keep an eye on the releases page.

Another upcoming feature for fdir is the ability to use async iterators rather than callback-style APIs. This should come with a massive reduction in memory usage and will look something like this:

ts
import { fdir } from 'fdir'

const files = fdir().crawl('/path/to/dir').withIterator()

for await (const file of files) {
  console.log(file)
}

Since this means fdir doesn't need to hold the full set of files in memory, it should be far better in large projects than the current callback API.

Thanks to @thecodrr for all the work on this πŸ™

tinyglobby ​

tinyglobby also has some unreleased performance improvements on the horizon, almost doubling its CPU performance in some cases.

Most notably, the underlying filtering in tinyglobby had a large rework which bumped performance massively.

Much of this was made possible by introducing some reproducible benchmarks to the project. These have allowed the maintainers to track down and fix performance bottlenecks in various places.

For example, here's the result of searching for packages/*/tsconfig.json in TSESLint's monorepo before the changes:

| Task name | Throughput avg (ops/s) | Throughput med (ops/s) | |

Show full content

July 18, 2025

Community Showcase (Q2 2025) ​

A little late, but it's time for another community showcase! πŸŽ‰

So many good things have happened over the last quarter in the community and around the ecosystem, and there's so much more to come πŸš€

Prettier CLI ​

The Prettier team has been collaborating with the e18e community for some time now on a new, faster CLI for Prettier. In June, this was released behind a flag for all to try out! πŸŽ‰

This has been a great collaboration, driven mostly by the work of @fabiospampinato and plenty of help from @fisker on the Prettier side of things.

You can see some of the huge performance improvements in the chart below:

prettier run time results

You can use this in your own project by using the new experimental flag:

sh
# via the CLI flag
prettier . --check --experimental-cli

# via an environment variable
PRETTIER_EXPERIMENTAL_CLI=1 prettier . --check

Without any other changes, this should speed up your formatting runs a whole lot πŸ™Œ

Read more about how we got here in the blog post.

e18e CLI ​

We posted about the upcoming e18e CLI some time ago and the rough idea behind it. Since then, the community has been hard at work building it and shaping the definition of what's to come.

Soon you will be able to do cool things like this:

sh
npx @e18e/cli migrate chalk # automatically migrate chalk to picocolors

npx @e18e/cli migrate --interactive chalk # interactively choose which library to migrate chalk to

npx @e18e/cli analyze # lint your dependency tree and produce useful stats

We now have the basics in place and a much fuller list of features to work towards. Just a few of the things this CLI will be able to do:

  • Automatic migrations to suggested replacements
  • Lint your dependency tree for common issues
  • Lint your publishing setup (with help from publint!)
  • Visualise CJS vs. ESM usage in your project
  • Bring your own codemods and replacements lists (so the CLI can migrate and detect migrations of your own internal dependencies)

We're also working towards having a GitHub automation which can create these migration PRs for you, and run the lint steps in your CI.

If you want to contribute or if you just want to test the CLI as we build it, we'd love the help. Come join us in the e18e Discord and join the #cli channel!

You can also follow along with the release roadmap in the roadmap issue.

Huge thanks to @paul, @passle and @fuzzyma for all the work so far.

Storybook 9 ​

Storybook recently released version 9! πŸš€

This release comes with all sorts of improvements like Storybook Test, story generation and much more. However, the highlight for us is by far the install footprint reduction and project complexity improvements.

Just look at this graphic taken from their post:

storybook 9 dependency graph

They've almost flattened their dependency tree! This is some great progress and the result of many months of work by the Storybook team - much of which involved collaborating with the e18e community.

You can read more about how they achieved this and how they're keeping on top of it in their blog post.

We also recently held a webinar where Jeppe from the Storybook team and James from e18e discussed the technical details behind these improvements. You can watch the recording on YouTube: Lessons learned from reducing bloat in Storybook where they dive deeper into the process and lessons learned.

Big thanks to the Storybook team for taking a lead on this kind of improvement, and for working so closely with the community throughout ❀️

ESM-only migration ​

Ever since require(esm) became a thing, we've been pushing to move more and more projects to ESM-only. Helping maintainers with the migration has been high up on our list, and we've made great progress.

On top of that, we're seeing a lot more migrations happening outside the community as more and more maintainers are choosing to follow suit.

Here's just a few projects we've seen migrated:

Some future migrations on the horizon too:

Thanks to @michael.faith for migrating some of these, and the maintainers who made the move themselves!

fdir ​

With help from @sxzz and @thealexlichter, fdir is now bundled using tsdown. This has lead to almost a 3x reduction in install size and a much faster build time for the maintainers!

This is unreleased as of writing, but will be coming soon. Keep an eye on the releases page.

Another upcoming feature for fdir is the ability to use async iterators rather than callback-style APIs. This should come with a massive reduction in memory usage and will look something like this:

ts
import { fdir } from 'fdir'

const files = fdir().crawl('/path/to/dir').withIterator()

for await (const file of files) {
  console.log(file)
}

Since this means fdir doesn't need to hold the full set of files in memory, it should be far better in large projects than the current callback API.

Thanks to @thecodrr for all the work on this πŸ™

tinyglobby ​

tinyglobby also has some unreleased performance improvements on the horizon, almost doubling its CPU performance in some cases.

Most notably, the underlying filtering in tinyglobby had a large rework which bumped performance massively.

Much of this was made possible by introducing some reproducible benchmarks to the project. These have allowed the maintainers to track down and fix performance bottlenecks in various places.

For example, here's the result of searching for packages/*/tsconfig.json in TSESLint's monorepo before the changes:

Task name Throughput avg (ops/s) Throughput med (ops/s) 'tinyglobby' '891 Β± 1.35%' '981 Β± 131' 'fast-glob' '1822 Β± 0.68%' '1878 Β± 110' 'glob' '1725 Β± 0.61%' '1767 Β± 95' 'node:fs glob' '923 Β± 0.67%' '941 Β± 74'

And the result after the changes:

Task name Throughput avg (ops/s) Throughput med (ops/s) 'tinyglobby' '2254 Β± 0.42%' '2312 Β± 89' 'fast-glob' '1868 Β± 0.60%' '1903 Β± 103' 'glob' '1714 Β± 0.58%' '1754 Β± 85' 'node:fs glob' '927 Β± 0.78%' '983 Β± 49'

In many cases, this now makes tinyglobby the fastest glob library available.

Keep an eye on the releases page for when this becomes available!

The library also recently passed 20M downloads/week on npm, a great achievement for the maintainers and the community!

Thanks to @superchupu and @benmccann for these huge improvements πŸ”₯

npmgraph suggested replacements ​

The npmgraph tool now suggests replacements for your dependencies!

To do this, it uses the community-driven module-replacements project.

This is such a great addition, and will be a huge help for finding optimisations in your project.

All thanks to @broofa for implementing this! πŸŽ‰

Project collaborations ​

We've seen another great few months of collaborations, both with projects and with individual maintainers.

h3 ​

h3 is a tiny HTTP server framework by one of our favourite people - @pi0!

Often one of the largest and/or most complex dependencies is the web server, and the various middlewares and dependencies it pulls in. h3 is a super nice alternative to many of these - staying small, close to the platform, and incredibly fast.

A really awesome collaboration recently was one between pi0 and reve to introduce compiled routes. This allows you to compile a static routing table at build time, resulting in some huge performance boosts.

Definitely check out both h3 and the underlying router, rou3.

react-router ​

With lots of help from @MichaelDeBoey, we've been busy at work collaborating with the React Router team to clean up a bunch of dependency clutter, unused code and start some discussions around modernisations of some parts of the project.

All sorts of clean up has been going on - including running knip across the project, migrating to native functionality, and a possible future "unforking" of clack.

As part of the upcoming Remix v3, there's also the new node-fetch-server worth keeping an eye on. This is a new web server built on top of Node primitives and a fetch-like API.

Big thanks to MichaΓ«l and the React Router team for holding these discussions and helping the community follow the contribution process, too.

Netlify ​

Some time ago, we reached out to the Netlify team to see if the community can help modernise and clean up some of the Netlify CLI. A few months later, we've seen many discussions happen and many PRs land. A lot of good collaboration has happened, and the Netlify team has done a lot of good work internally aligned with our goals.

Notable changes include:

  • Dropped support for Node 16 and below in Netlify build (used by Netlify CLI) - this resolved vulnerabilities, reduced the install size and upgraded a whole bunch of dependencies
  • Removed 71 dependencies from Netlify CLI
  • Reduced the install size of Netlify CLI
  • Improved the performance of the Netlify CLI by 2-3x (changelog)

It has been awesome to see a company collaborating with the community on this and sharing their roadmap/vision. Big thanks to @philippeserhal in particular for being active in the community and helping get contributions over the line.

Get involved ​

If you'd like to help out, come join our discord and say Hi!

https://e18e.dev/blog/community-showcase-q2.html
Improving Prettier performance with the new CLI
Show full content
Improving Prettier performance with the new CLI ​

June 23, 2025

Over the last several months, we've been working with the Prettier team on a new version of the Prettier CLI. Today, I'm happy to announce that it is now available behind a flag in the latest version of Prettier!

Try it out! ​

To use the new CLI, install Prettier 3.6.0:

sh
npm i prettier@latest

You can then enable the experimental CLI like so:

sh
# via the CLI flag
prettier . --check --experimental-cli

# via an environment variable
PRETTIER_EXPERIMENTAL_CLI=1 prettier . --check
Community investigation ​

We started investigating the performance of Prettier in the e18e community after noticing it was quite slow in various larger projects. Given how widely used it is, this would be a great opportunity to improve performance for huge amounts of people in one go.

Through a lot of CPU profiling and debugging, we discovered that much of the time was lost in the CLI rather than in the formatter itself.

At this point, Fabio popped up and pointed out that he was also tackling this a few years ago! He already had a work-in-progress CLI he had been building with the Prettier team, and had already done some great investigation work.

There, we decided to collaborate and finish the new CLI together, getting it over the line to be released in the next version of Prettier.

You can read a deeper dive into this in his blog post, along with how he architected it and the results.

What's changed? ​

The new CLI is a complete rewrite of the existing one, with a focus on performance and modernisation.

From the outside, the CLI should feel and look the same. However, under the hood it has various performance improvements and a much smaller footprint.

Just some of the gains:

  • Built in parallelism
  • Improved caching layer
  • Faster config file resolution
  • Leaner dependency tree
Results ​

If we run this against the TSESLint codebase, we can see a significant performance improvement:

sh
$ time npx prettier --check .
Checking formatting...
All matched files use Prettier code style!
npx prettier --check .  34.24s user 7.39s system 141% cpu 29.407 total

$ PRETTIER_EXPERIMENTAL_CLI=1 time npx prettier . --check
Checking formatting...
All matched files use Prettier code style!
PRETTIER_EXPERIMENTAL_CLI=1 npx prettier --check .  54.18s user 4.76s system 647% cpu 9.096 total

That's 9 seconds in the new CLI, vs 29 seconds in the old CLI!

If we run this again, it'll get even faster now that the cache is populated:

sh
Checking formatting...
All matched files use Prettier code style!
PRETTIER_EXPERIMENTAL_CLI=1 npx prettier . --check  2.78s user 1.08s system 231% cpu 1.671 total

So now we're at 1.6 seconds vs the original 29 seconds!

If we turn parallelisation and caching off, we still see a significant improvement:

sh
$ PRETTIER_EXPERIMENTAL_CLI=1 time npx prettier --no-cache --no-parallel --check .
Checking formatting...
All matched files use Prettier code style!
PRETTIER_EXPERIMENTAL_CLI=1 npx prettier --check --no-cache --no-parallel .  19.26s user 2.01s system 172% cpu 12.313 total

12 seconds, still much faster.

prettier run time results

Wrap up ​

Big thanks to Fabio, pralkarz and @fisker for working together on this with me (@43081j).

This has been a great community effort, with months of collaboration happening and a lot of back and forth in the Discord.

Get involved ​

If you want to get involved in projects like this, join us on our Discord and we'll be happy to pair up.

https://e18e.dev/blog/prettier-speed-up.html
Community Showcase (Q1 2025)
Show full content

April 3, 2025

Community Showcase (Q1 2025) ​

It has been a while since we posted one of our monthly showcases. This is mostly because the community has been hard at work on some exciting but rather large projects!

Today, we're going to give some updates on those and share what we've been up to. We'll also be switching these posts to be quarterly since much of the work is longer running, but we'll still be posting about other things in between! ❀️

e18e CLI / web report ​

One of the pain points in adopting recommendations from the e18e community has been the fact that it mostly involves manual work and joining the dots between various tools.

For example, just some of the great tools we use today:

  • arethetypeswrong - analyzes your package for TypeScript publishing/configuration problems
  • publint - verifies that you publish your package correctly
  • node-modules.dev - analyzes your dependency tree and various other aspects
  • eslint-plugin-depend - analyzes your dependencies for replaceable/redundant packages

These tools are often combined with various manual processes and scripts to do the investigation work of what we can improve in a package.

This makes it very difficult for maintainers to check their own packages for possible improvements. We want to solve this and provide good enough tooling that you can do it yourself, with ease.

That is why we are now working on an e18e CLI and somewhere we can produce reports for packages on the web. Our vision is that you can throw your package name or package.json into this tool and see all of the recommended changes, warnings, etc.

This is very early stage right now and being worked on by antfu, blu and 43081j, but will be coming very soon! πŸ™Œ

Prettier CLI ​

For the last couple of months, we have been hard at work on the new prettier CLI. The idea is that this will eventually replace the current one, but initially be available behind a flag.

But why do we need a new one? Well, a little bit of backstory...

Some time ago, we were digging through CPU profiles of prettier, trying to figure out why it was particularly slow in some larger projects. It turns out, much of the slowness comes from things we often don't need.

For example, prettier currently allows you to override the config at any level, but we don't actually see much use of that in the wild. However, just in case you do use that, the CLI has to check every directory for each supported format of prettierrc. This is very expensive when you know you don't have any.

We raised this in the e18e discord, and found that Fabio already started work on a new CLI a few years ago to solve this and many other performance issues!

The project had gone a little stale since he hadn't worked on it for some time, but we kicked off a new piece of work to get the ball rolling again.

Initial tests with this have often shown a 10x speed up on formatting a large repo πŸŽ‰

There's still work to do, but keep an eye out for another announcement once we're ready to start trials!

ESLint performance ​

We recently started discussions around the performance of ESLint. As usual with a pluggable tool, many of the performance issues come from plugins rather than ESLint itself. So, we started work on various plugins to improve their performance.

It is also worth noting that, while there are extremely fast alternatives to ESLint these days, many of us can't switch over or don't want to (e.g. if we rely on plugins that haven't been ported over). That is why it is still important we improve what we can in the ESLint ecosystem.

Just a few wins we've seen so far:

typescript-eslint vitest migration ​

A while ago, we started a conversation around migrating the TSESLint repo from jest to vitest.

The idea was that this would greatly improve test run performance, modernise some of the tests themselves and lighten the install size for maintainers.

Around the same time, we discovered Arya had already been working on this for a few months in some unfinished branches. From there, we decided to lend a helping hand in reviews and such to help get this over the line.

Arya has done a huge amount of work moving every sub-package of the repo to vitest one by one, and we're now at the stage where many of them are near enough ready to merge.

This is a great example of where it will not affect the end user directly, but will speed up CI and maintainer workflows significantly.

If you want to follow the work, keep an eye on the tracking issue.

Stream cleanup ​

Streams are very useful for dealing with large amounts of data in a performant way. You'll find them in use in most of the tools we use today, especially those which deal with reading large files, network resources, etc.

Over the years, many packages have been published to provide utilities for dealing with these. For example, utilities to create pipelines, buffer windows, concatenation and much more

These have all been of great use, but many have since been made redundant by Node itself shipping similar functionality in the stream module.

For example, you can now use the built-in pipeline function for transforming a stream through a pipeline of transforms:

ts
pipeline(source, transform1, transform2, (err) => {
  if (err) {
    // error thrown
  }
  else {
    // pipeline finished successfully
  }
})

In an effort to clean up these redundant usages, and use the built-in standard library, the community has been contributing to many different projects and removing them.

Just a few packages which have seen improvements:

Huge thanks to v1rtl for leading this effort!

Collaborations ​

This year, we've taken more of a focus on collaborating with organisations involved in open source. Our community can't do all of this work alone, so helping organisations do some of this themselves will go a long way and ultimately impact the user a lot more in many cases.

Here's just a few of the projects and organisations we've been collaborating with:

We're also continuing to collaborate with storybook, vite, svelte, and many other projects.

Events ​

This year, we're putting more effort into attending conferences and meet ups. This has given us some great opportunities to meet people from the community in person, and to introduce more people to it πŸŽ‰

At some point we will also be looking to do talks at events like this, so keep an eye out!

Amsterdam meetup ​

As part of this, we also had our first ever meetup πŸ₯³ Taking place in Amsterdam, we had a great turnout and a lot of productive discussions.

e18e Amsterdam Meetup

Big thanks to the people who managed to make it ❀️ There will be more of these in future, so come along if you're able to and meet some of the community.

Svelte Summit ​

Svelte summit is this May! Both patak and 43081j will be around, so if you'll be there, come say hi!

We've collaborated a lot with the svelte community in the past, so this will be an exciting opportunity to meet some familiar faces in person and talk about where we can help in future.

ViteConf 25 ​

ViteConf 25 was recently announced and will be taking place in Amsterdam this October.

Quite a few of the e18e community will be attending. If you'll be there too, let us know, as we'd love to catch up πŸ™

Get involved ​

If you'd like to help out, or you're a maintainer and want to collaborate more closely, join our discord and say Hi!

https://e18e.dev/blog/community-showcase-q1.html
Migrating the ecosystem to ES modules
Show full content

March 19, 2025

Migrating the ecosystem to ES modules ​

Node made some huge steps forward recently by releasing require(esm) to each of the long-term support versions (other than the soon to fall out of LTS 18.x). Awesome work by @joyeecheung getting it over the line!

This is awesome work and unblocks a huge amount of packages on the migration path from CommonJS to ES modules πŸŽ‰

So let's have a look into what's next and how the e18e community is trying to help!

require(esm) ​

One of the main blockers in the CJS vs ESM story has been interop. You could import CJS from within an ES module, but could not require an ES module from within a CJS module.

This left us with two options at the time for a migration path:

  • Change much of the code to be async, such that we can use a dynamic import (which does work in CJS modules)
  • Change all CJS dependencies of our ES module package to be ES modules

The ideal is the latter, that everyone uses ES modules. However, this obviously isn't feasible since not all packages are maintained and it'd be a crazy amount of work to replace them.

So we were blocked...

That is until require(esm) came along! This basically means we can require an ES module inside a CJS module now. CJS packages can consume ES module packages and vice versa. A huge move forward and unblocks us all to get back on the migration path!

For example:

ts
// file: foo.cjs

// chai is esm only, but this now works!
const { expect } = require('chai')
Types of package ​

As part of this migration, we have three types of package to deal with:

  • ESM packages
  • CommonJS packages
  • Dual packages
Migrating a CommonJS package ​

In most cases, this is as simple as doing the following steps:

  • Set type to "module" in package.json
  • Update all imports to include file extensions
  • Update sources to use export / import syntax

For example, in package.json:

json
{
  "name": "my-package",
  "type": "module"
}

And updating the imports:

ts
// before
import './foo'

// after
import './foo.js'

It is preferred that you have file extensions, but if you want to expose extensionless imports to your consumers, you can use an export map:

json
{
  "exports": {
    "./foo": "./foo.js"
  }
}
Migrating a dual package ​

Dual packages are basically a necessary evil if you want to support both CJS and ESM before require(esm) was available and don't want to force your CJS users to use an async dynamic import.

These packages work by having two copies of the sources and the types.

Fortunately, this doesn't increase the package size much since it will be compressed anyway. However, it does increase the on-disk size (once extracted by npm).

Most people shipping TypeScript packages like this will be using a tool like tsup or tshy.

Those shipping JavaScript often just use a bundler like esbuild to create two bundles (or one and the sources).

To migrate from these setups, we mostly need to do the same steps as migrating a CommonJS package from above.

Some maintainers may still want to use their choice of tool/bundler, so in those cases we can configure the tool to no longer output CommonJS.

For example, in tsup:

json
{
  "name": "my-package",
  "type": "module",
  "tsup": {
    "format": ["esm"]
  }
}
How the community is helping ​

Within the e18e community, we have been tracking the migration from CJS to ESM in an issue for some time.

It is a crazy amount of work for us to try migrate every possible package, so we have opted for the approach of helping migrate high impact tools, starter kits, frameworks and what not. This should hopefully help others to follow suit and give plenty of example migrations to work from.

Who has migrated so far? ​

We've already seen a huge amount of packages make the jump. Here are just a few (some of which were assisted by e18e, and some not):

This is just a subset of the packages we've seen migrate, many more PRs are still in progress by contributors and maintainers alike.

Migrating ESLint plugins ​

One place we can easily contribute to this effort is the migration of ESLint plugins.

ESLint already imports plugins under the hood, and so can support them in CommonJS or ES module format.

Migrating an ESLint plugin to ES modules will mean dropping support specifically for consumers who have flat configs written as CommonJS in a version of Node less than 20.x.

This is because flat configs in >=20 will have require(esm) available, and legacy configs (.eslintrc) will use import.

Migrating starter kits and frameworks ​

Another high impact place to help with this migration is in starter kits and frameworks. Many projects are created from these templates, so migrating them to ES modules will mean all new consumers automatically have the right setup.

We haven't yet started collaborating with these projects on this yet, but it is high priority in the pipeline.

Get involved ​

If you maintain a package and want some help migrating, let us know! Many of the community would be happy to chip in.

Similarly, if you want to help migrate packages with us, come say hi.

Join our discord and let us know you want to help!

https://e18e.dev/blog/migrating-the-ecosystem-to-esm.html
Bundling dependencies (and when not to do it)
Show full content

February 10, 2025

Bundling Dependencies (and when not to do it) ​

As part of e18e, the community is often asked when you should or shouldn't bundle your dependencies as a library or developer tool author.

Much of this has come around thanks to people noticing that Vite does indeed bundle most of its dependencies. Similarly, Storybook has been known to do the same.

So when is this the right thing to do, and when is it not?

What is pre-bundling / inlining / etc? ​

Before we continue, let's explain some of these terms and what's going on here.

If we inline a dependency, that usually means we take the source of it and copy it into our codebase rather than depending on it as an npm package.

If we pre-bundle (or just "bundle") a dependency, that would mean we run our library through a bundler like rollup before publishing it.

In both cases, the dependency is no longer taken from npm and is instead stored in our published package as if we wrote it ourselves (and are "dependency free").

Why? ​

There are a few reasons you may do this, though each is debateable on if it is the right thing to do or not.

So let's go through a few!

Dependency is CommonJS and you're targeting browsers ​

This one is somewhat valid and fairly common. You depend on a package which has no clear ESM alternative and you want your library to work natively in browsers.

If this is the case, ideally you would either move away from the package to an ESM alternative, or you would contribute upstream to add ESM support.

This isn't always possible though - e.g. if this is a fairly niche package or is no longer actively maintained.

Advice: If the dependency is unmaintained, consider building your own and contributing it back to the community. Either way, there should be a solution to this without bundling.

Using only a small part of the dependency ​

Sometimes, you may depend on a fairly large dependency but only actually use a tiny part of it.

While it is true that you can tree-shake the rest, that burden is then on your consumers who have to pull down an unnecessarily large dependency and have to remember to setup tree-shaking in the first place.

Bundling the dependency can solve this up front without the consumer having to.

Advice: Suggest that the authors extract this functionality into its own package (within reason), or find/create an alternative more focused package.

Internal dependencies ​

If you work in a monorepo, it is sometimes the case that you want to organise your code into sub-packages but don't necessarily want to publish all of those to npm.

In this case, it makes sense that you might bundle the internal packages at publish time, assuming you only use them in one package. If you use them in multiple packages, it probably still makes sense to publish them to gain from de-duplication.

A quick example would be a monorepo structured like this:

  • @org/library - the main library published to npm
  • @org/utils - a library only @org/library uses
  • @org/cli - a cli package published to npm
  • @org/text - a library used by @org/library and @org/cli

As you can see, @org/utils could be bundled into @org/library rather than being its own package. Meanwhile, @org/text is used by multiple published packages so should likely be published itself too.

Advice: If only used in one place, this is fine to bundle. Otherwise, publish the packages.

Being "dependency free" / "zero dependency" ​

Especially with e18e community raising awareness of dependency bloat (amongst many other things), people have been adding more focus to going "dependency free".

In some projects, this makes a lot of sense for various reasons. For example, using more of what the platform provides rather than dependencies.

However, some projects have seen this rise in demand for "dependency free", and tried to shortcut a solution by bundling all of their dependencies.

This just hides the fact that they still have a bloated dependency tree, and worsens things by removing npm's ablity to de-dupe dependencies. The bundling step does reduce some of the size, but still pulls in the same bloated tree which could've been replaced with leaner, more modern code.

These projects often include a vendor/ directory of their npm packages, or run a bundler at pre-publish time.

Advice: Put the work in and become dependency-free properly if possible (if it really should be).

Advantages & disadvantages ​ Advantages of bundling ​

We don't want to block our release waiting for a dependency to have an alternative

This may be waiting for an ESM alternative, something less bloated, or something using newer standards

We are producing a developer tool (i.e. it'll never reach production), so we want to tree-shake our dependencies for our consumers

This is the most common reason and still very valid. If you're shipping a developer tool and have a complex dependency tree with a lot of unused code, it may be better to tree-shake it up front.

We want to patch a dependency in a way that the dependency is unlikely to ever accept upstream

Less common, but you may want to patch something to work better in your particular case, in a way that the maintainers wouldn't be able to accept across the board.

Disadvantages of bundling ​

Packages no longer receive downloads

The number of downloads is a commonly used metric for sponsoring OSS projects, or deciding if to use such a package

Dependencies no longer receive updates

They will be locked to the version at the time of bundling. The burden to release security updates is then on you (to re-bundle)

Bloated dependency trees are hidden but still exist

These dependencies would be better replaced by alternatives, or contributed to

npm de-duplication no longer happens

If a consumer has many copies of this dependency, the bundled ones will be duplicates since npm isn't aware of them

Maintainers don't receive help/contributions to improve

Bundling the dependency often means the core problem is put off for longer (e.g. bloated sub-dependencies). Helping the maintainers solve the problem would be better

Issues are often opened with your project rather than the dependency

Since consumers don't know you pull much of your code from dependencies, issues with it will be raised with you rather than the packages responsible for it.

Additional notes ​ Tree-shaking in libraries ​

Bundlers are very good at tree-shaking these days, so you can quite easily pull in a larger library and only use part of it without needing to ship all of it.

However, if you're publishing a library, this means you're placing the job of tree-shaking onto your consumers (assuming you document that they should do it!).

This isn't great, but neither is the alternative (bundling the parts you use).

If possible, you really should try find a more appropriate package or create one which provides the part of the functionality you need.

Extracting new packages ​

Sometimes, a package has a piece of functionality you need but that accounts for a tiny amount of the overall size.

If this is the case, it often makes sense to extract it into its own package.

However, the line is very fine here.

If you extract something too little, you're publishing micro-utilities (which we're trying to avoid).

Ideally, you should extract groups of functionality into re-usable packages. A good example of this is empathic, a group of path utilities.

De-duplication ​

Whatever you do, if you bundle, you're at risk of removing the benefits npm gives of de-duplication.

Ideally, we want to declare our dependencies so we can leave npm to de-dupe and share them across other libraries being used in parallel to ours.

Real-world examples ​ Vite ​

Vite currently bundles most of its dependencies as a way to tree-shake things up front so its consumers don't have to.

Given that it is a developer tool, unused in production, this made sense at the time it was decided.

However, dependencies have vastly improved since then and the community has been hard at work improving performance across the board. Thanks to this, it is likely the Vite team will stop bundling some of their dependencies in future.

Many are now very lean and shipped as ES modules, using modern APIs, etc. These would now be better off moved outside of the bundle.

Storybook ​

Storybook bundles a lot of their dependencies, both internal and external.

Similar to Vite, they are a developer tool and rarely would reach production. Due to this, the decision made sense to keep the tree-shaking burden in-house rather than placing it on consumers.

Due to the complexity of Storybook, they also have many more dependencies than Vite. It doesn't make much sense to declare all of these if only very small parts of each one are used.

For these reasons, Storybook is likely to continue bundling dependencies it doesn't use in their entirety at least.

Conclusion ​

Given we don't always have the time to contribute upstream to our dependencies and clean things up, it may still be a valid temporary solution to bundle some of them.

If you're building a developer tool (e.g. a CLI), it may make sense to bundle long-term. Especially if your dependency tree is rather complex and contains a lot of code you don't actually make use of. This is exactly what Vite and Storybook are both doing.

If you're building a library, you generally should not be bundling your dependencies. It may make sense short term to unblock you, but ultimately should not stay that way (ideally dependencies improve over time).

https://e18e.dev/blog/bundling-dependencies.html
The journey so far
Show full content
e18e - Journey so far ​

January 6, 2025

Journey so far Cover Image

This month we're skipping the usual monthly showcase post to write a little about what we got upto in 2024 and what lies ahead for us in 2025 πŸš€

Before we start, a little about me - I'm one of the creators of e18e and can be found in most places as @43081j. I maintain and contribute to a whole bunch of things but have been focusing on this community for the past year.

Enough about me though! Let's take a look at some history and what lies ahead for us as a community.

Way back... ​

For a long time, I found myself returning many times to the need for a more performant JavaScript ecosystem.

As far back as 2017, I was involved with depcheck, a tool which detects unused dependencies amongst other things. I worked on a whole bunch of features and fixes for this tool so I could start introducing it to projects to keep a closer eye on dependency trees.

Around the same time as this, I was submitting PRs to various projects to remove redundant polyfills, one-liner packages and a few other things.

Every few months, I'd think about this again and start submitting another bunch of cleanup PRs.

I even made a few attempts at creating repos to share this effort (e.g. you-dont-need-x and eslint-plugin-clutter).

Unfortunately, none of these efforts really went anywhere. I struggled to find anyone who cared and would often move on to something else for a few months before I got the itch in my brain to tackle it again.

Starting a cleanup ​

Eventually, I created the ecosystem-cleanup project as place to track performance improvements in popular open source projects.

In the early days, this was basically me creating issues for myself to contribute to various OSS projects. Things like:

  • Removing redundant polyfills
  • Upgrading packages
  • Replacing large packages with lighter, more focused ones
  • Replacing unmaintained packages with modern, maintained alternatives

It was a lot of work for one person, but I kept chipping away in the hope that I could raise awareness of performance and start to improve some of the ecosystem.

Over time, the maintainers of the projects receiving these contributions started to focus more on performance themselves, and we got a few contributors to the cleanup issue tracker!

Beginnings of a community ​

A few years later, @bluwy was posting about his efforts to speed up astro's tooling. Around the same time, @antfu quote posted this with the following:

Would be cool if we have a "full-time perf optimizers" for the ecosystem πŸ‘€

A lengthy discussion later, @antfu, @bluwy, @patak and I came up with the idea for e18e!

Many of us care about ecosystem performance just as much as each other, but never had a space to collaborate or even share that we're working on similar things. The e18e community has connected us so closely and given us a place to grow together.

Finding like-minded people ​

In the first couple of days, we went out to find others who were working on similar things and might want to collaborate.

To name a few:

All of these people and many others were working on some aspect of performance. Seeing them connect and have a space to collaborate was awesome ❀️

Results so far ​

Several months later, here's a few stats from the past year:

Most of these PRs and issues are umbrella style, in that they're used to track contributions to many projects.

This is really impressive work by the community, as it has resulted in hundreds, if not over a thousand contributions to many high impact projects around the ecosystem.

Graphs like this dependency reduction of svelte-preprocess are becoming a common sight:

graph showing the dependency tree of svelte-preprocess in version 5 vs version 6

Projects focusing on performance ​

To get an idea of some large projects focusing in this space now:

Projects & tools ​

Another big win by the community has been the number of projects it has helped gain adoption, and the projects launched by members.

To name a few:

I could go on, but there are far too many to list.

Some of these already existed before e18e, but the community has done great work driving adoption of them and collaborating with the maintainers (all of whom are in our community!).

The year ahead ​

What a great year it has been! ❀️

We will continue most, if not all of the work we've been doing in the past year. Much of it will start showing results this year as more people install newer versions of packages we've had an effect on.

There is more to do though!

Speed up ​

We spent a lot of 2024 focusing on cleaning up dependency trees, modernising packages and helping people lean more into platform functionality.

Much of this fits into the cleanup category of the e18e initiative.

In this new year, it would be great to put some time into the speedup category too. This is often much deeper, long running work since it involves performance testing amongst other things.

Tooling ​

A lot of what we do is still a manual process, and developers still don't have the right tools to detect much of this stuff automatically.

We'd love to spend time this year on creating a good toolchain for helping take better care of dependency trees and finding performance bottlenecks.

Automating a lot of the investigation work would also be a huge win.

Lots to think about! Some of this will be kicking off in the discord server early in the year.

Meet up ​

Early in 2025, we will be organising the first in-person e18e meetup!

We haven't decided yet what the structure of this will be (just a social, or something more), but we will post more details very soon.

It'll be great to see people connecting, and what awesome ideas come out of it!

Get involved ​

We'd love to have you in our community, whatever it is you're working on.

You can help by contributing, or even just by telling us some of the stories of problems you've seen yourself.

Join the discord and come say Hi!

https://e18e.dev/blog/journey-so-far.html
November contributions showcase
Show full content
November contributions ​

December 3, 2024

November Contributions Cover Image

Another month, another great list of performance gains across the ecosystem. This month, we've also seen a huge effort to improving visibility of these things so more people can get involved. Let's take a look!

Libraries ​ kasi ​

A set of utilities we've seen quite often in the wild are case transforms. For example, transforming to and from camel case (e.g. from foo-bar to fooBar).

Often, this has been achieved by using a micro-utility dependency or by repeating a very similar function to everyone else who needed this logic.

This is a really good example of something which is too big to be copied everywhere, but too small to justify its own package.

So what do we do in these cases? We group the common case transforms and use that as a library.

That is exactly what Fabio has done with kasi!

kasi is a great collection of functions for transforming between various cases (pascal, camel, snake, etc). Instead of pulling in many micro-packages, or repeating code, we can now use this.

Great work as always, Fabio! πŸ™

unicode-segmenter ​

As part of the bluesky contributions mentioned later in this post, some of the community noticed a large chunk of the JS bundle was taken up by graphemer.

This library is used to split or count the number of grapheme clusters in a string (i.e. the visual symbols we would perceive as individual characters). It does a good job at this but comes in at a whopping 812KB!

Fortunately, @hyeseong.kim came along and built unicode-segmenter πŸŽ‰ This library achieves the same functionality at a fraction of the size (147KB).

Really great work here. This helped us reduce bundle sizes in a whole bunch of projects.

sonda ​

As part of the cleanup effort in the e18e space, it is a common need that we want to analyze the bundle of a project. Usually, we do this to find duplicate dependencies, oversized dependencies and so on.

In the wild, there are not many tools to do this analysis and do it accurately. This has left us with often manually inspecting bundles and the process taking a lot longer than it should.

All good, though, Filip has come to the rescue with his new tool: sonda!

Sonda is a bundle analyzer which works with all popular bundlers and accurately determines the bundle contents by leaning on sourcemaps. This works great and has already helped us with many investigations into footprint reduction of some projects πŸ™

fuzzyma's e18e tools ​

Another great contribution to the community recently is a tool by @fuzzyma which can determine the dependents of a given package.

Feel free to explore e18e-tools source and an example of the produced output.

This is such a useful tool since we have no easy API access to find this information right now.

In many of the issues of the cleanup project, we now have an incredibly useful list of all the top dependents of the target package. This is making the cleanup work so much easier.

Big thanks to @fuzzyma and @devminer.xyz for making this a thing!

Contributions / Improvements ​ bluesky ​

Some fun collaboration kicked off in the e18e discord recently. A few members of the community started looking into the bluesky bundle size, and noticed a few inefficiencies πŸ‘€

While digging around, they noticed zod was included twice in the bundle!

A simple lockfile update allowed this to be de-duped, and shaved off a fair chunk of the bundle.

Super work here by @marvinh.dev and @jviide.iki.fi πŸŽ‰

You can read more about the investigation and the solution in the pull request.

Other news ​ deoptexplorer ​

More of a "you should know about this" than news - deoptexplorer is an extremely useful VSCode plugin to help you find deoptimisations in your code.

In the community, we have started using it heavily to find performance bottlenecks in many different popular tools.

Big thanks to microsoft for building this! Check it out and maybe you'll find some performance improvements πŸš€

require(esm) unflagged in Node 22.x ​

In Node 22.x, the ability to require(...) ES modules has been unflagged and enabled by default!

This is huge news and should open many doors for us being able to migrate libraries to ESM-only. We should also be able to gradually start removing dual-package publishing from various popular packages and go all in on ESM.

Read more about this in Node's blog post.

Excellent work by @joyeecheung as always πŸ™

vite 6.0 ​

A big milestone this month - vite 6.0 was released!

This new release has a huge number of changes and, in the context of e18e, has a great list of performance improvements many of our community worked on.

One big change is the the migration to tinyglobby. This alone introduced a good size reduction and performance boost πŸš€

On top of that, various other dependency upgrades and performance improvements mean this is by far the fastest and smallest vite so far. Great work as always by the team and the community ❀️

e18e social (Bluesky) ​

We recently decided to move our main social account to Bluesky. Given that most of the e18e community has already made this same move, it seemed to make the most sense that we do so too.

Our other social accounts will likely stick around for archive purposes, but we will most actively be posting on Bluesky.

If you haven't already yet, you can follow us on Bluesky!

Get involved ​

If you want to help out, join the discord. We'd love to have the help πŸ™

https://e18e.dev/blog/november-contributions-showcase.html
October contributions showcase
Show full content
October contributions ​

November 4, 2024

October Contributions Cover Image

A few days late again because I was caught in another typhoon 😬, but here's the latest wins from the e18e community!

Libraries ​ picospinner & nanospinner ​

Two small but great additions, these CLI spinner libraries are here to replace heavier weight alternatives like ora.

picospinner was recently adopted into the tinylibs organisation, and is being lead by Pondwader.

nanospinner author @usmanyunusov has also recently joined the e18e community and is actively helping move things forward.

Both of these libraries are great alternatives and unblock a whole bunch of future migrations. Looking forward to see more!

empathic / fd-package-json ​

As part of the cleanup project, we needed an alternative package for finding the closest package.json. To fill the gap, fd-package-json was created and recently passed 800,000 downloads/week!

However, we still had many gaps where we wanted to traverse for other files and directories without having to pull in a heavy library.

This is where empathic comes in!

Another great library by @lukeed, this provides a bunch of useful utilities for dealing with paths and traversals.

This library can easily replace many of the find-up-like packages floating around the ecosystem:

ts
import * as find from 'empathic/find'

// Find closest "foobar.config.js" file
const file = find.up('foobar.config.js', { cwd })

Let the migrations begin!

nano-staged ​

Another one by @usmanyunusov, nano-staged is a tiny replacement for lint-staged.

Benchmarks show it is much faster, and comes in with a much smaller footprint (currently only 47kB, 1 dependency).

This is another easy migration we will soon be kicking off across the ecosystem πŸš€

milliparsec ​

In the web server space, milliparsec has gained a huge amount of usage as a replacement for body-parser.

At only 11kB, this is much smaller than older alternatives, and much faster!

Excellent work by v1rtl on building this and actively working on feedback from the community ❀️

Contributions / Improvements ​ Storybook ​

The Storybook team has continued to pour effort into improving the performance and install footprint in collaboration with the e18e community, as we reported on last month.

The biggest win by far this month was migrating from express to polka, installing 69 fewer dependencies and decreasing the install size by 6 MB! πŸŽ‰ The effort was initially led by @43081j and driven home by Jeppe Reinhold of the Storybook core team.

The team has also been on a dependency-prebundling-spree to cleanup and tree-share dependencies across @storybook/builder-vite, @storybook/react and @storybook/addon-docs, removing a total of 77 dependencies.

To ensure none of these gains are lost in future, they also did some great work to add benchmarking to all new pull requests. This is a super nice idea for making sure we don't regress. Hopefully other projects can implement similar in the near future πŸ™

ESLint plugins (and removing older Node support!) ​

A big win for the community this month - removing support for very old Node versions in a few popular ESLint plugins πŸŽ‰

For some time now, these plugins have been a source of considerable bloat for those of us who do not need to support such old engines. It is awesome to see the source projects finally dropping these polyfills in new major (breaking) versions.

Just a couple of plugins that are moving ahead on this:

None of these have been released yet but they are well on their way and are being supported by the maintainers.

Do note, the community lead alternatives will certainly live on as they drop even more opinionated dependencies and logic. If you want to reduce your install footprint and get some performance gains, check out the alternatives docs for them here:

strip-ansi ​

The community had a realisation recently that strip-ansi can be replaced very easily by the built-in stripVTControlCharacters!

Since then, Namchee, @ari_perkkio and others have contributed a whole raft of PRs migrating away from the library.

This was a great catch and has allowed us to drop the dependency in dozens of projects already.

If you're using Node 16.x and above, you can drop this one too!

Docusaurus ​

This one didn't originate from e18e but is still well worth a mention. Docusaurus is currently tackling a pretty huge project of improving build performance.

Great to see another large project taking a focus on performance πŸ™

They have already shaved off minutes from their build times πŸ”₯ very impressive work by @sebastienlorber and the team.

Other news ​ require(esm) in Node ​

@joyeecheung and others have recently been working hard on allowing Node to require(...) ES modules.

For example, this means the following code would now work:

ts
// chai 5.x is ESM only
const { expect } = require('chai')

Until now, many of us have been publishing "dual packages" - packages which contain both CommonJS and ES module syntax.

This is unfortunate since it means we're often shipping double our package size in order to support both systems.

With the ability to require ES modules, this will all change and we should be able to ship only ESM! πŸŽ‰

As part of this becoming available, the e18e community is preparing to help in a few ways:

  • Migrate projects pinned to older CJS versions of dependencies to their later, ESM-only versions
  • Migrate projects with a dual package setup to ESM-only
  • Migrate projects which have type: "module" but also have CJS exports to ESM-only

Huge reductions will happen once we are able to stop publishing dual packages. Big wins ahead!

If you want to help out with this, we're tracking the work on GitHub.

porffor passes 50% of ECMAScript tests ​

If you haven't seen it yet, check out porffor, a very cool experimental ahead-of-time JavaScript compiler/engine.

Built by @canadahonk (an active member of our community ❀️), porffor has the potential to become an extremely useful tool for producing much smaller and faster WASM binaries.

Instead of packaging a runtime alongside the code, porffor will compile down to native (which comes with huge performance gains).

Recently, the biggest win has been to see the engine pass 50% of the Test262 tests! Read more in Porffor passes 50% of Test262.

e18e on Bluesky ​

The e18e community now also has a profile on Bluesky: e18e.dev.

Give us a follow and we'll post updates on the cool stuff happening in the community! πŸ¦‹

Get involved ​

If you want to help out, join the discord. We'd love to have the help πŸ™

https://e18e.dev/blog/october-contributions-showcase.html
September contributions showcase
Show full content
September contributions ​

October 6, 2024

It's that time of month again where we show off some of the great contributions we've seen around the e18e community in the past month!

Libraries ​

This month has been a great one for improvements to existing and upcoming libraries. Many have been listening closely to the e18e community and pushing forward together.

chokidar 4.x ​

chokidar is a library for watching for changes on a file system. Built on top of node's own watcher capabilities, it provides a higher level and simpler interface.

Almost all of us depend on this library in some way, often through the toolchain or framework we use.

@paulmillr, the author of chokidar, and I (@43081j) have been working hard to get the next major version of it over the line for a long time now (the branch was made in 2021!).

Recently, we finally released 4.0.0! πŸ₯³ This massively reduces the size and complexity.

Those of you who remember the is-number fiasco on social media will now also be super happy that we (chokidar) were the largest consumer of it and have since dropped it entirely πŸŽ‰

Big wins for the e18e community!

Thanks to @benjaminmccann and talentlessguy for contributing many v3 to v4 upgrades already!

fdir / tinyglobby ​

fdir was in last month's showcase but has earned another mention thanks to the author (thecodrr) landing various community contributed PRs and features.

This is a great example of where an author has joined the community and worked closely with it to further their library, and provide some much needed fixes and features.

In version 6.4.0, we saw two important changes:

  • Ability to exclude symlinks
  • Ability to bring your own glob library (e.g. zeptomatch)

These two changes have helped the community migrate even more high level tools and frameworks across.

Similarly, tinyglobby has shipped a few new versions and hit 1M downloads/week. This is amazing work, especially keeping up with the feature requests and feedback of people migrating.

Thanks to pralkarz, @benjaminmccann and @superchupudev for already migrating so many projects to these two libraries!

tinyexec migrations ​

The community has been working wonders migrating countless projects from execa, ez-spawn, and other libraries to the super lean tinyexec.

For example, thanks to pralkarz, vitest has already moved over!

There are many more PRs currently in progress to do just the same πŸ™ Great work by the community here.

Contributions / Improvements ​ Storybook ​

The Storybook team have been working closely with the e18e community for some time now, dedicating huge amounts of time to improving the performance and install footprint for everyone.

This month, they've kept up the pace! Just a few examples of what has landed:

  • Migrated from chalk to picocolors
  • pralkarz migrated from fs-extra to built in fs functions
  • Removed handlebars and simplified templating internally
  • Removed prettier from the core bundle (saved 10MB on the install size)
  • Replaced lodash with es-toolkit (more huge savings, especially with tree shaking)

On top of this, the team has actually started a full project focusing on reducing the install footprint in collaboration with the e18e community.

For anyone interested in helping out in the e18e space, this issue a great way to learn some of the techniques used to track down bundle/install size issues.

As a bonus, they even integrated visual bundle size analysis into their CI so all new PRs can be compared with the main branch. They did this by generating esbuild metafiles for all of their packages every time they're built and storing links to the esbuild Bundle Size Analyzer website with those metafiles embedded. The final result is a visual overview of all package's bundle, that you can play around with in the Chromatic visualizer.

We would love to see this in more projects! You can get inspiration from the PR that implemented the work.

This has all been great to see and will hopefully lead to other large projects making similar efforts! Definitely some big wins ahead πŸ™Œ

nx ​

The folks over at nx have been incredibly active with the e18e community. They are definitely on the same page and have been moving fast to work with the community to land many improvements.

You can see a lot of this in the tracking issue over on the ecosystem cleanup project. These issues are closing quickly, with contributions coming from a few different people in the e18e space.

Just a few examples of the improvements made:

  • Migrating older fs-extra code to use newer, native fs functionality
  • Migrating from chalk to picocolors
  • Migrating from glob libraries to fdir

These are all improving the CPU performance of nx and cutting huge subtrees out of the dependency tree at the same time.

changesets ​

The changesets project recently started collaborating directly with the e18e community and we've already seen a good amount of optimisations contributed.

There's a tracking discussion if you want to get involved.

It is awesome to see the maintainers of a large project working so closely with the community on these things ❀️

Big thanks to @bluwyoo and @andaristrake for getting this setup!

jimp ​

jimp, an image manipulation library, has reduced their package size by an impressive amount:

  • Before: 120MB, 392 packages
  • After: 25MB, 66 packages

This is awesome work πŸ™Œ

Bonus: ViteConf ​

ViteConf happened recently and had some amazing talks across all topics.

While it didn't happen in September, it still deserves a mention thanks to how many of the talks mentioned the e18e community.

Our own Bjorn did an excellent talk on performance. Similarly, the great people at Storybook explained a lot of their efforts to reduce their install footprint and how they've collaborated with the e18e community.

Get involved ​

If you want to help out, join the discord. We'd love to have the help πŸ™

https://e18e.dev/blog/september-contributions-showcase.html
August contributions showcase
Show full content
August contributions ​

September 7, 2024

This post is a little late thanks to me being stuck in the middle of a super typhoon, but here's some highlights of what the community has been up to in August!

If you want to get involved, remember to come join the discussion!

Libraries ​

Here are just some of the great libraries we've seen this August.

tinyexec ​

tinyexec is a new library from the tinylibs group to provide a super lightweight abstraction around child_process.

Usage is familiar and simple:

ts
import { x } from 'tinyexec'

await x('npm', ['install'])

In many places where we need to launch a command, we don't need a high level abstraction so we can save a lot on performance and footprint by using this instead.

vitest, nuxt, astro, and many others have already moved over.

For places where we do want a higher level interface, we still have projects like zx.

tinyglobby / fdir ​

Much of the community has been hard at work moving projects away from various heavyweight glob libraries to fdir.

fdir is a very fast and lightweight library for traversing the file system and has optional glob support.

Already a great contributor in the e18e space, @superchupudev has also provided us with tinyglobby.

tinyglobby adds a useful layer on top of fdir for when you still need a glob interface and consistent behaviour with other glob libraries:

ts
import { glob } from 'tinyglobby'

const files = await glob(['src/*.ts'])

So many projects have been quick to adopt these libraries, saving on install size and getting great performance gains at the same time. To name a few:

Great work by both @thecodrr and @superchupudev here!

package-manager-detector ​

package-manager-detector is used to detect the local package manager (e.g. npm, pnpm, yarn, etc.)

Much lighter than other alternatives, this package has quickly been adopted by many projects across the ecosystem.

As an example, @benjaminmccann switched from preferred-pm (1MB) to package-manager-detector (28KB) in changesets and svelte-add recently. Great work πŸ™

Thanks to @antfu7 and @userquin for building this!

tschema ​

tschema is a cool new library to generate JSON schema types by @lukeed05.

Super light and fast, this is another package quickly being adopted in the e18e space.

ts
import * as t from 'tschema'

const User = t.object({
  uid: t.integer()
})
knip ​

knip is a tool for detecting unused files and dependencies in your project. This has been incredibly useful and widely used across the e18e community already.

For example, mocha has already adopted this and cleaned up a huge amount of deep dependencies thanks to the efforts of @voxpelli.

Contributions / Improvements ​

As well as some cool new libraries, we've seen many great contributions to performance and clean up across the ecosystem.

dotenvx ​

The maintainers of dotenvx have been hard at work with @superchupudev to massively reduce the install size and depedency tree complexity.

Down from 142 dependencies to only 28 dependencies, this is a great achievement πŸŽ‰

changesets ​

The changesets project has been busy merging many e18e-focused improvements.

Just a quick look at the changelog, you can see many of our community have been working to reduce the dependency tree and increase performance.

Thanks to @bluwyoo, @benjaminmccann and @trivikram in particular for pushing this forward πŸ™

picocolors ​

picocolors has been around a while already, but recently published a new version with support for bright variants of colours.

This has allowed many, many projects to migrate to it from other slower and larger libraries.

If you need terminal colors, this is the one to use.

If you're using node 20 or above, and don't need to support older runtimes, also check out styleText which is built in!

payload CMS ​

The payload CMS team have been doing some impressive work optimizing the install size and performance of their packages.

Some quick stats:

  • Before: 277MB, 603 packages
  • After: 54MB, 148 packages

To get an idea of the change, take a look at the npmgraph before and after.

postcss ​

The PostCSS maintainers improved postcss-mixins, with its size going from 1.3MB to 930KB, dropping ~15 dependencies. Great work by @sitnikcode and the team, continuing their long tradition of caring about the size of their user’s node_modules.

Get involved ​

If you want to help out, join the discord. We'd love to have the help πŸ™

There are still many gaps to fill with new libraries, many contributions to existing libraries to be had, and many performance gains to be achieved.

https://e18e.dev/blog/august-contributions-showcase.html
July contributions showcase
Show full content
July contributions ​

August 5, 2024

The e18e community has been flourishing lately. We've seen a huge amount of contributions across the ecosystem, all the way upstream to some of the deepest dependencies.

Most of us will have been affected by these contributions somewhere down the line, giving us better performance and a smaller footprint.

The people contributing these changes deserve so many thanks for their work, so here is a summary of some of the highlights from the past month!

svelte-preprocess becomes dependency-free ​

The svelte team have been busy reducing the footprint of svelte-preprocess.

The before and after values speak for themselves:

  • Before: 1.5MB / 26 packages
  • After: 97KB / 1 package

npmgraph of svelte-preprocess

You can read about how this was achieve through these two PRs in particular:

codemods ​

One of the biggest steps forward with the replacements project has certainly been the codemods repo.

If you haven't yet seen the replacements project, it basically provides community driven lists of suggested replacements to npm packages. These are then consumed by various tools, such as the eslint plugin.

The codemods project is another consumer of these lists. It provides a place for the community to contribute codemods which can automatically migrate your code to a given replacement package or native functionality.

@passle_ has done great work here starting and maintaining the codemods project, and the community have contributed many codemods already.

The future of the es-tooling organisation will likely involve a CLI which can apply these codemods for you. Keep an eye out for it in future!

Removing is-number from micromatch ​

While this hasn't been published yet, it is great progress, showing that even some aged projects are open to performance contributions.

This change removed, in this case, an unnecessary dependency often seen in the ongoing cleanup work.

is-number may be small but is often entirely unnecessary. Most consumers can instead use something as simple as typeof n === 'number' and provide a stricter API rather than trying to coerce inputs.

Credit to @talentlessguy for this contribution!

Removing rimraf from node-pre-gyp ​

Node has had a recursive option for rmdir (or rm in newer versions) for a while now. This can achieve the same functionality rimraf was providing in many cases.

A small but effective win here is the removal of rimraf from node-pre-gyp.

It is worth mentioning, for those cases where you'd still like a CLI, you can use an alternative.

Credit to @benjaminmccann for this one!

picoquery ​

As part of the cleanup project, we were in need of a fast and lightweight query-string parser/stringifier.

Some excellent solutions exist for part of this:

  • URLSearchParams for general parsing and stringifying of query strings
  • fast-querystring: a very fast query string parser with support for arrays

Though a gap existed for the speed of fast-querystring, but the functionality of something like qs (object nesting, arrays, custom delimiters, etc).

This is why picoquery was born! A super fast and small configurable query string library.

Our hope is that we see more and more of these alternatives being produced by the community. Many popular, bloated or outdated packages still need alternatives. Join the discussion if you're interested!

neotraverse ​

Similar to how picoquery came about, we needed a lighter alternative to the popular traverse package.

Big thanks to @puruvjdev for making this happen by publishing neotraverse!

The savings are great:

  • traverse: 3.9MB / 67 packages
  • neotraverse: 140KB / 1 package
package-size-calculator ​

Built by @DevMiner, this is a cool little CLI that can provide package size stats and an estimate of the monthly bandwidth usage.

Many people have been using this already in the e18e community to get a rough idea of potential savings by changing dependencies.

Combining this with npmgraph and pkg-size is a great way to investigate how to improve a package.

https://e18e.dev/blog/july-contributions-showcase.html
ES Tooling - community-led e18e-focused tooling
Show full content
ES Tooling ​

July 22, 2024

The e18e initiative has seen huge growth since launch. We've seen hundreds of performance contributions upstream to popular projects, and the creation of many community-led tools.

A notable example of this is the ES Tooling community GitHub organization.

If you haven't yet encountered e18e, read more in the guide and join the community.

A home for e18e-focused tools ​

Over the last few months, many of us have collaborated and connected through the e18e community. The ES tooling organization is a result of that - a place for us to store and own forks, tools, and other code bases we're working on together.

A few popular projects that were running solo until now, have come together to create this:

While e18e exists to connect us all and provide a space to collaborate, it doesn't exist to own the projects coming out of the initiative. That is where projects like es-tooling, unjs and more come in to play.

We expect es-tooling will be one of many community-led orgs with an e18e focus.

Ecosystem cleanup ​

One of the projects which kicked much of this initiative off - the ecosystem cleanup project has now moved into the ES Tooling organization to allow better visibility and maintenance.

The cleanup project exists primarily as an issue tracker, tracking:

  • Footprint reduction in popular packages
  • Missing forks or alternatives that could be worked on
  • Performance improvements in popular packages

If you want to help out, this project is a good starting point to find some open issues.

Read more at the ecosystem cleanup project.

Module replacements ​

The module replacements project is a community-led list of popular npm packages and their possible replacements.

Often, these replacements are native, or much faster and more modern packages. If you know of a good alternative to something, get involved and add to the list!

Read more at the module replacements project.

Module replacements codemods ​

The module replacements codemods project is an effort to automate the ecosystem cleanup. Taking the module replacements as input, we aim to have automated codemods for all packages listed. This way other tooling can use these codemods to perform transformations on projects automatically. For example, a codemod for the is-even package would result in:

Before:

js
const isEven = require('is-even')

console.log(isEven(2))

After:

js
console.log(2 % 2 === 0)

We'll also be looking into implementing a CLI around these codemods so people can run them on their own projects, or so they can run them on other projects and create pull requests to them, hopefully simplifying the amount of effort it takes to replace dependencies.

You can find more information about the module replacements codemods repository. If you're interested in seeing the before/after states of the codemods, take a look at the test fixtures. Every codemod has one or more before/after examples available.

What's next? ​

If you own an e18e-focused project, or need a home for a new project, get involved!

https://e18e.dev/blog/es-tooling.html
e18e (Ecosystem Performance) - A new community initiative
Show full content
e18e (Ecosystem Performance) ​

June 28, 2024

Today, we are excited to announce e18e!

e18e is a community initiative to bring together people who are passionate about improving performance in the JavaScript ecosystem. Our goal is to provide a space for knowledge sharing, contributions and ideas.

e18e (Ecosystem Performance)

Our focus is on three main areas:

  • cleanup - reducing, simplifying and modernizing dependency trees.
  • speedup - speeding up core packages and frameworks.
  • levelup - providing modern, lighter alternatives to core packages.
Clean up ​

Over time, many of us build up deeply nested trees of dependencies and lose sight of what we actually depend on. This often results in us relying on packages which are no longer maintained, or are slow, or bloated, etc.

Often there are already actively maintained, battle tested alternatives but maintainers are unaware or do not have the time to move to them.

There are several efforts to help these maintainers out by replacing or updating such dependencies:

Speed up ​

Many of the core packages we depend on could benefit from performance improvements. Given how fundamental some of these packages are, a performance gain could widely affect the ecosystem in a positive way.

Some examples of these performance optimizations:

Level up ​

Many well established packages have grown over time to fit more and more features, configurability and so on. Sometimes, we have use cases where this is too much for what we need, and would rather go back to the core functionality.

In those situations, the community has recently been building lighter alternatives - packages which often come with zero dependencies and very small install/bundle sizes.

Just a few great alternatives to common libraries:

Get involved! ​

e18e is a place to help us all connect and collaborate. If you're interested in joining some of the different efforts from folks in the community, or just want to check out what's going on - Join the e18e discord!

https://e18e.dev/blog/e18e.html