Open-source project
e18e/module-replacements avatar
e18e/module-replacements

module-replacements is a shared list of dependencies you can probably drop

A manifest of JS modules and their more modern/active replacements

1,013 stars106 forksTypeScriptMIT

At a glance

What is it?
The e18e module-replacements project maintains a manifest that maps JavaScript modules to more modern alternatives, split into three lists of differing opinion, and publishes it as an npm package, as raw JSON and as documentation. It is aimed at anyone doing a dependency audit who wants a shared, reviewed answer to the question of whether a package is still needed, rather than a private opinion.
Who is it for?
module-replacements is worth adopting as the shared reference for a dependency cleanup, because the value is the review behind the list rather than the list itself, and a project that argues about which packages to keep in a pull request will waste that argument repeatedly.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A dependency audit that needs shared answers

The problem is the long tail of a package.json. Most projects carry a handful of dependencies that everyone suspects are unnecessary, a polyfill for a feature the platform has shipped for years, a small utility that could be three lines, and a package that stopped being maintained two years ago. Each removal is a small decision that gets argued repeatedly, in every repository, by people who have not read the source. module-replacements is part of the community e18e effort, and it exists to make that decision once and publish it. The project provides two things, manifests, which are mappings of modules to their possible replacements, and documentation for more complex replacements where a mapping is not enough. The audience is dependency maintainers and anyone running a cleanup, and the interesting design choice is that the list is data rather than a linter rule, so it can be consumed by a lint rule, by a package registry front end, or by a human reading a document.

Three manifests, and the difference is how opinionated they are

There are three manifests, and the distinction between them is the most useful thing in the repository. The native replacements manifest, exported as nativeReplacements and stored as native.json, lists modules that can now be replaced by native functionality. The example given is pseudo-polyfills, which provide the functionality of widely available platform features and can be replaced by their platform equivalents, and it also covers features that did not exist at the time but have existed in the platform for many years and no longer need a dependency. The micro utility manifest, microUtilsReplacements and micro-utilities.json, is described as more opinionated, listing modules considered to be micro utilities, very small utilities that could possibly be replaced with native equivalents or removed entirely. The preferred manifest, preferredReplacements and preferred.json, is the most opinionated of the three, and often the replacements are much lighter or more modern than the modules they replace. Sometimes these are also actively maintained forks of older, unmaintained source packages, which is the case where a mapping needs the documentation rather than a one-line swap.

Consuming it from npm or as a plain JSON file

The package is published as module-replacements and is installed like any other dependency:

sh
npm i -S module-replacements

You then import the manifest of the choice, for example the native one:

ts
import {nativeReplacements} from 'module-replacements';

The manifests are also shipped as files in the manifests/ directory of the package, so a path such as node_modules/module-replacements/manifests/native.json is available to a tool that would rather read JSON than import JavaScript. That is a deliberate design choice for a data project, since a build script, a shell command or a CI check can all read the same file without a runtime dependency. The package is side-effect free, its main entry is dist/main.js, and the published files are dist and manifests, so what consumers get is the compiled module and the raw data and nothing else. A full list of replacements is also rendered on the e18e website, and the schema for the manifest format is published as manifest-schema.json in the repository root, which means a manifest can be validated independently of this package.

Three tools already consume the manifests

The manifests are useful because other projects read them, and the README names three. eslint-plugin-depend from the es-tooling organisation is an ESLint plugin to detect possible replacements. @e18e/eslint-plugin is the official e18e ESLint plugin. And npmx is described as an alternative npm frontend, which is the interesting case of the three, because a registry front end can warn you at install time rather than in a later review. The division of labour is sensible. The lint plugin catches a dependency you already have, the registry front end catches one you are about to add, and the documentation catches the cases where neither can decide, because the mapping is a judgement about a package's behaviour rather than a name match. If you are evaluating this project, the honest first question is not what is in the list but which of these consumers your team would actually turn on, since the list alone is a document and the tools are what turn it into a habit.

The engines data decides which platform versions count

The build scripts show how much machinery sits behind the manifests. There is a generate-schema script that produces the manifest schema, a validate-modules script run as a lint step with node --experimental-vm-modules, a sort-manifests script to keep the files ordered, and an update-manifest-paths script that rewrites the dist paths inside the manifests. The largest group is the update-engines family, with a script per platform: update-engines:web, update-engines:bcd, update-engines:runtimes, update-engines:node and update-engines:bun, plus an update-engines aggregator and a prepublishOnly hook that runs it. The bcd script stands for the browser compatibility data, and the development dependencies include the @mdn/browser-compat-data package, which is where the browser side of the platform support information comes from. The reason this matters is the native manifest's own rule. A module can only be listed as natively replaceable once the platform feature is widely available, so the data about platform support is not decoration, it is the criterion for entry. The package.json version field reads 1.0.0 while the published releases are tagged 3.4.0, 3.3.0 and 3.2.0, so the tag and the manifest version are tracked separately.

Contributions are reviewed, and new platform features wait

The contribution rule is short and specific. If you want to add a replacement mapping to one of the manifests, you open an issue where it can be discussed. And there is a caveat that tells you the entry criteria, that very newly available native features are unlikely to join the list since they are not widely available yet. That is the project applying its own standard consistently, and it is also the practical instruction for anyone trying to add an entry. The alternatives in a mapping are not always simple, and the documentation exists for the more complex replacements, so a proposal has to come with the reasoning rather than a package name. The project is MIT licensed, the repository carries a LICENSE file, a CONTRIBUTING.md, a prettier configuration and an editor configuration, and it uses pnpm with a lock file. The releases move steadily, 3.2.0 on 2026-08-18, 3.3.0 on 2026-08-24 and 3.4.0 on 2026-09-20, and the last push was on 2026-10-19, which is a sensible cadence for a dataset that follows the platform's own releases.

Where a shared list stops being enough

Three limits are worth naming. The first is that the list is a name mapping, and a name mapping can be wrong. A polyfill is replaceable with a native feature in general and not in your application, if you support an old browser, if a bundler polyfills it back, or if your build targets a runtime that does not have the feature. That is exactly why the engine data exists, and why the projects consuming the manifests are configurable rather than automatic. The second is that the preferred list is opinionated, and a project that depends on a package for compatibility with a specific framework version, or that values the stability of an old release over a newer one, has a legitimate reason to stay where it is. The third is scale. A manifest covers common cases, and it does not cover the long tail of one-off utility packages, which is where most of the actual weight in a large dependency tree sits. A reasonable approach for a team is to run the native list first, since those are the least controversial, treat the preferred list as a set of proposals to discuss rather than a set of commands to run, and keep your own notes on the packages you decided to keep, since the next audit will ask the same question again.

Editorial conclusion

module-replacements is worth adopting as the shared reference for a dependency cleanup, because the value is the review behind the list rather than the list itself, and a project that argues about which packages to keep in a pull request will waste that argument repeatedly. It is the wrong tool when you need a decision about a specific package that nobody has reviewed, and it is the wrong tool for a codebase that deliberately depends on old packages for compatibility reasons, since the preferred list is opinionated by design. Before adopting it, read the three manifests and pick the one that matches your policy, since applying the preferred list to a project that only wants the native list will produce arguments rather than removals, and check the engine data, since the scripts that update it decide which platform versions a replacement is considered safe for.

Frequently asked questions

What is the difference between the three module-replacements manifests?

The native manifest lists modules that can be replaced by native platform functionality, the micro utility manifest is a more opinionated list of very small utilities that could be replaced natively or removed, and the preferred manifest is the most opinionated, listing modules whose replacements are often lighter or more modern, sometimes as actively maintained forks.

How do I install and use the module-replacements package?

Install it with npm i -S module-replacements, then import the manifest you want, for example import {nativeReplacements} from 'module-replacements'. The raw manifests are also available as files in the manifests/ directory of the package, such as node_modules/module-replacements/manifests/native.json.

Which tools consume the module-replacements manifests?

The README lists three: eslint-plugin-depend, an ESLint plugin to detect possible replacements, @e18e/eslint-plugin, the official e18e plugin, and npmx, an alternative npm frontend.

Can I add a new replacement to the manifests?

Yes, by opening an issue where the mapping can be discussed. The project notes that very newly available native features are unlikely to join the list, since they are not yet widely available.

Official sources

  1. e18e/module-replacements on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/e18e-module-replacements.svg)](https://hysenlabs.com/projects/e18e-module-replacements)

Was this useful?