No More Libraries? A Comprehensive Guide to npm Packages You Can Replace with Built-in APIs (2026 Edition)
This article comprehensively covers areas where "a popular library exists, but the standard is now good enough," from both the browser and Node.js perspectives. The target environment is Node.js 24 LTS (Krypton) and later, along with Web APIs available in all major browsers.
TL;DR
- In browsers,
fetch,structuredClone,crypto.randomUUID(),URLSearchParams, Set methods, and Iterator helpers are all available as standard. Many use cases for axios and lodash are no longer necessary - In Node.js, global
fetch,node:test,--watch,--env-file,fs.glob,util.styleText, and--strip-typesare stable in LTS. They can replace node-fetch, nodemon, dotenv, chalk, and ts-node - The biggest benefit of "sticking with the standard" is reducing supply chain risk and bundle size by cutting dependencies. However, some areas like interceptors remain difficult to cover with standard APIs alone
Background: The axios Supply Chain Attack and Why "Sticking with the Standard" Matters
On March 31, 2026, axios, an HTTP client with over 100 million weekly downloads, was hit by a supply chain attack. A threat actor linked to North Korea compromised an npm account and published malicious versions (1.14.1, 0.30.4). These automatically installed a cross-platform RAT (Remote Access Tool) through a fake dependency package called plain-crypto-js. axios is estimated to be present in about 80% of cloud environments, making the impact enormous.
What this incident symbolizes is "the risk of continuing to use a library when the standard can do the job." Now that fetch is globally available in both browsers and Node.js, there is little reason to include axios as a dependency for simple HTTP requests. One fewer dependency means one fewer attack surface.
Against this backdrop, the JavaScript/TypeScript ecosystem has been moving toward "incorporating features into the standard."
On the browser side, the number of APIs that work consistently across the four major engines (Chrome, Firefox, Safari, Edge) has grown. ECMAScript 2025 standardized Set methods and Iterator helpers, and in March 2026, Temporal reached Stage 4.
On the Node.js side, v18 added global fetch and node:test, v20 added --env-file and --watch, v22 added fs.glob and util.styleText, and v24 brought TypeScript type stripping and global URLPattern. As of Node.js 24 LTS, many npm packages that were once needed during development can be replaced with built-in features.
The stance of this article is "if the standard can do it, stick with the standard." Reducing dependencies not only cuts bundle size and maintenance costs but also directly reduces the attack surface for supply chain attacks.
Browser
fetch: Replacing axios
MDN: Fetch API / Node.js: Global fetch
fetch is available as standard in all browsers, and has been globally available in Node.js 18+ (internally based on undici). The main reason for using axios -- "working in both browser and Node" -- is now achievable with the standard alone.
Timeouts can be written concisely with AbortSignal.timeout() (MDN) (supported in major browsers since 2024).
To combine multiple signals, use AbortSignal.any() (also supported since 2024).
However, fetch lacks request/response interceptors, automatic retries, and progress events. If you need these, consider axios or the lighter ky (~2KB). For simple API calls, fetch is sufficient.
structuredClone: Replacing lodash.cloneDeep / deepmerge
MDN: structuredClone() / Node.js: structuredClone()
structuredClone() is available as standard in all browsers and Node.js 17+. Deep copying in a single line.
However, it cannot copy functions, DOM nodes, Error objects, or prototype chains. lodash is still needed for copying class instances. For JSON-serializable data structures, structuredClone is sufficient.
crypto.randomUUID: Replacing the uuid Package
MDN: Crypto.randomUUID() / Node.js: crypto.randomUUID()
crypto.randomUUID() generates v4 UUIDs. Available in browsers and Node.js 19+.
However, if you need UUID versions other than v4 (v1, v5, v7, etc.), the uuid package is still required. For v4 only, the standard is sufficient.
URLSearchParams: Replacing query-string
MDN: URLSearchParams / Node.js: URLSearchParams
URLSearchParams is available as standard in all browsers and Node.js.
Note that URLSearchParams handles array values differently from query-string (for foo=1&foo=2, you need to use getAll("foo")). Unless you need complex query string parsing, the standard is sufficient.
Object.groupBy / Map.groupBy: Replacing lodash.groupBy
Object.groupBy was standardized in ES2024 and is available in all major browsers.
Use Map.groupBy when you want to use objects as keys.
Set Methods: Replacing Manual Implementations and lodash
ES2025 added mathematical set operation methods to Set, now available in all major browsers.
Previously, manual implementations like [...a].filter(x => b.has(x)) or lodash's _.intersection were needed, but now these run natively and efficiently.
Iterator Helpers: Replacing lodash-style Chaining
ES2025 Iterator helpers (supported in major browsers since March 2025) enable lazy evaluation chaining as a standard feature.
Iterator.from() also works with generators and any iterable. Since no intermediate arrays are created when processing large datasets, memory efficiency is improved.
Temporal: Replacing moment/dayjs
MDN: Temporal / TC39: proposal-temporal
Reached TC39 Stage 4 in March 2026, with native support in Chrome 144+ and Firefox 139+. Immutable date/time operations are now possible as a standard feature.
However, Safari and Edge still require a flag, so using a polyfill (temporal-polyfill) in production is recommended. The polyfill is skipped when the browser has native support. Stable availability across all browsers is expected in late 2026.
URLPattern: Replacing path-to-regexp
MDN: URLPattern / Node.js: URLPattern
URLPattern has been supported in major browsers since September 2025. In Node.js 24, it is available globally.
Useful for implementing routing without a framework or for request matching within Service Workers.
Node.js
Global fetch: Replacing node-fetch
Since Node.js 18, fetch is globally available (internally based on undici).
The node-fetch package is no longer needed. However, if you need advanced undici-specific features (connection pool control, HTTP/2, etc.), use import { request } from "undici" directly.
node:test: A Candidate to Replace Jest/Mocha/Vitest
Stable since Node.js 18. A zero-dependency test runner available via node:test.
Well suited for unit testing libraries, CLI tools, and backends. The zero-dependency nature is effective for speeding up CI and reducing Docker image size. However, if you need snapshot testing, rich matchers, UI mode, or browser testing, Vitest/Jest still have the advantage. For new Node.js library development, node:test is worth considering as the first choice.
--watch: Replacing nodemon
The --watch flag has been available since Node.js 18.11 (stable in Node.js 22+).
To watch only specific paths, use --watch-path.
However, if you need fine-grained configuration via .nodemonrc (ignore, delay, ext specification, etc.), nodemon still has the advantage. For simple restarts, --watch is sufficient.
--env-file: Replacing dotenv
The --env-file flag has been available since Node.js 20.6.
No need to import dotenv in your application code -- just add it to your package.json scripts.
package.json
fs.glob: Replacing the glob Package
fs.glob and fs.promises.glob were added in Node.js 22.0 and stabilized in 22.17 LTS.
The standard fs.glob returns an AsyncIterable, so if you want an array, you need to collect entries with for await...of. Option support (like ignore) is limited compared to the glob package, but for simple pattern matching, the standard is sufficient.
fs.rm: Replacing rimraf
fs.rm can recursively delete directories with the { recursive: true, force: true } option (available since Node.js 14.14).
Same applies in shell scripts.
The original purpose of rimraf -- Windows-compatible recursive deletion -- is now solved by fs.rm.
util.styleText: Replacing chalk
util.styleText was added in Node.js 20.12 and stabilized in 22.17 LTS.
However, if you need complex styling with template literals or custom themes, chalk still has the advantage. For simple colored log output, util.styleText is sufficient.
TypeScript Type Stripping: Replacing ts-node/tsx
Introduced as --experimental-strip-types in Node.js 22.6, and enabled by default for .ts files in Node.js 24 LTS.
It only strips type annotations without performing transpilation. Syntax that requires JavaScript code generation -- such as enum, namespace, and constructor parameter properties (public x: number) -- will cause runtime errors.
However, if you use enum, path aliases (paths), or need to target Node.js 22 or earlier, tsx is still needed. For new projects, it is recommended to avoid enum in favor of as const and design for compatibility with Node.js's built-in type stripping.
Summary
As of 2026, the areas where "the standard is sufficient" are steadily expanding. The following table summarizes the correspondences.
| Legacy Library | Standard Replacement | Environment |
|---|---|---|
| axios (simple requests) | fetch + AbortSignal.timeout() | Browser + Node 18+ |
| lodash.cloneDeep / deepmerge | structuredClone | Browser + Node 17+ |
| uuid (v4) | crypto.randomUUID() | Browser + Node 19+ |
| query-string | URLSearchParams | Browser + Node |
| lodash.groupBy | Object.groupBy | Browser + Node 21+ |
| Manual Set operations | Set.prototype.intersection etc. | Browser + Node 22+ |
| lodash chaining | Iterator helpers | Browser + Node 22+ |
| moment / dayjs | Temporal | Chrome 144+, Firefox 139+ |
| path-to-regexp | URLPattern | Browser + Node 24+ |
| node-fetch | Global fetch | Node 18+ |
| nodemon | node --watch | Node 22+ |
| dotenv | node --env-file | Node 20.6+ |
| glob | fs.glob | Node 22+ |
| rimraf | fs.rm | Node 14.14+ |
| chalk | util.styleText | Node 22+ |
| ts-node / tsx | node --strip-types | Node 24+ |
| jest / mocha | node:test | Node 18+ |
As noted in each section, standard APIs do have limitations. However, reducing dependencies benefits security, performance, and maintenance across the board. For new projects, we recommend starting with standard APIs and adding libraries only when they fall short.