close
close

Cleaning up and accelerating the JS ecosystem – Journey so far

Cleaning up and accelerating the JS ecosystem – Journey so far

I’ve been working hard on improving performance across the ecosystem for a while now. Mostly by cleaning up old dependency trees, reducing install footprints, and improving CPU/memory performance of commonly used dependencies.

In this blog post I will try to briefly explain the trajectory that led to e18e and the cleanup of the ecosystem.

Thoughts on Micro Utilities

Microtools contribute greatly to the installation size and especially to the complexity of the dependency tree of many projects.

Packages such as is-number And is-nan fall into this category.

The important thing is that many of these packages are useful in certain situations, but certainly not in the general usage scenario.

Usually they can be replaced in the following situations:

  • They were written at a time when equivalent native functionality did not exist, but now there is.
  • They do more than what the consumer needs

Example: is-number

For example, is-number determines whether a value is a number or a string that resembles a number but is not NaN or +/-Infinity.

In some projects this is a repeated piece validation which can be better accommodated in its own module or package.

In general, many consumers have the NaN And Infinity validation, or even to support numerical strings.

This opens up a number of possible improvements in various projects. We can replace the use of this package in those projects with much simpler inline logic (e.g. in many real-world projects we have safely switched to typeof n === 'number' (because those projects later already started from the assumption and assumed that the value was a real number).

Another example: is-regexp

You can test whether something is a regular expression using instanceof: v instanceof RegExp.

However, in some situations (for example when using virtual contexts) this will not work, because RegExp is not the same class that v comes from. In those cases we should use something like:

Object.prototype.toString.call(obj) === '(object RegExp)'
Go to full screen mode

Exit full screen

If you don’t want to inline such code and want to support virtual contexts or something like that, a library might be a solution.

In many cases, however, the projects did not support virtual contexts anyway (and did not want to). This opens up opportunities to simplify it again to a simple instanceof.

Support for older runtimes

Another potential area for improvement is legacy runtime support.

Quite a few very popular packages have very deep dependency trees of various polyfill-like modules. These generally exist for one or both of the following reasons:

  • To protect against manipulation of the global namespace
  • To maintain support in runtimes that lack this functionality

Many of us don’t need this level of backwards compatibility and could see big performance improvements if we could reduce it.

Of course, it is important to note that there are still people who Doing must work within those constraints. That’s why we’ve often offered forks or alternatives in this area rather than trying to change the existing packages (which wouldn’t be open to such changes anyway).

Start improving things

I started thinking about these specific areas in 2018 or thereabouts after seeing how large and deep-rooted my node_modules were even for the smallest projects.

My first few attempts at change were to create some kind of ESLint plugin that could detect these packages and suggest removing them. Every few months I would have the same idea and try again, but I never really got where I wanted to be.

During this time I have worked on several large projects to clean up and improve what I could (one project I have been working on for a long time is Storybook).

Clean up the ecosystem

Next I created the Ecosystem Cleanup, a repository for reporting potential performance improvements in the ecosystem (essentially an issue tracker). Again, this was essentially me and my own personal issue tracker for a while, but at least it was visible in the public eye.

Shortly after that I started seeing people getting involved and contributing to upstream projects. I was so happy to see this, as I had been working on this myself for years and wondered if I was making a difference at all. It helped so much to see others getting involved, because I knew someone else cared.

Module replacements

While the cleanup project was and still is incredibly useful, we didn’t really have a place to share with the rest of the community what good alternatives existed.

To solve this, I created the Module Replacements project.

This project essentially contains a number of JSON lists of modules that could potentially be replaced and their proposed alternatives. These are currently divided into three levels of “strictness” or “opinionatedness”: native (modules that can be replaced by native functionality), micro-utilities (modules that can be replaced by simple inline code), and preferred (modules that we think should be replaced by more performant alternatives).

Codemods

The next step of the replacement project was to create a set of codemods so that we could automate the replacement of some of these modules.

Led by @passle, this project quickly received a large number of contributions in the form of various code mods.

The codemod team has also done a great job porting these to the codemod platform. In the future we also plan to offer them via some kind of CLI or autofix rules.

e18e

The turning point where I think all of us who care about these kinds of things found each other was e18e.

Bjorn was doing a great job improving astro’s performance, and Marvin had written similarly about accelerating the ecosystem. Eventually our paths crossed and we had some great discussions on the side.

A small group of us worked together to see if we were all on the same page and if there was a community to build from, and then e18e came along!

Built to be a community space for people to collaborate on improving the performance of the ecosystem, it has shown us how much people care about these things. So many have joined and contributed huge amounts already. We see accelerations and reductions in the ecosystem almost every day.

A little thanks

The community is growing rapidly and has too many people to thank for their contributions. However, I would like to thank these people in particular for helping to make this community possible:

In the same way, people who were already working on projects that simultaneously contributed to the same goals: