もうライブラリ不要? 標準APIで置き換えられるnpmパッケージ総まとめ (2026年版)

この記事はAIによって生成されています。内容の正確性にご注意ください。

この記事では「有名ライブラリはあるが、標準で十分になった」領域を、ブラウザとNode.jsの両面から網羅的に整理する。対象はNode.js 24 LTS (Krypton)以降と、主要ブラウザで利用可能になったWeb APIとする。

TL;DR

  • ブラウザではfetchstructuredClonecrypto.randomUUID()URLSearchParams・Setメソッド・Iteratorヘルパー等が標準で使える。axiosやlodashの多くのユースケースは不要になった
  • Node.jsではグローバルfetchnode:test--watch--env-filefs.globutil.styleText--strip-typesがLTSで安定した。node-fetchやnodemon・dotenv・chalk・ts-nodeを代替できる
  • 「標準に寄せる」最大のメリットは依存数の削減によるサプライチェーンリスクの低減とバンドルサイズの削減。ただしインターセプター等、標準では難しい領域も残る

背景: axiosサプライチェーン攻撃と「標準に寄せる」意義

2026年3月31日、週間1億ダウンロードを超えるHTTPクライアントaxiosがサプライチェーン攻撃を受けた。北朝鮮に関連する脅威アクターがnpmアカウントを侵害し、悪意あるバージョン(1.14.1, 0.30.4)を公開。これらは偽の依存パッケージplain-crypto-jsを通じてクロスプラットフォームRAT(遠隔操作ツール)を自動インストールするものだった。axiosはクラウド環境の約80%に存在するとされ、影響範囲は甚大だった。

この事件が象徴するのは「標準で代替できるのにライブラリを使い続けるリスク」だ。fetchがブラウザとNode.jsの両方でグローバル利用可能になった今、単純なHTTPリクエストのためにaxiosを依存に含める必要性は薄い。依存が1つ減れば、攻撃対象面が1つ減る。

こうした背景のもと、JavaScript/TypeScriptのエコシステムは「標準に機能を取り込む」方向に動いている。

ブラウザ側では、主要4エンジン(Chrome, Firefox, Safari, Edge)で共通して動作するAPIが増えた。ECMAScript 2025ではSetメソッドやIteratorヘルパーが標準化され、2026年3月にはTemporalがStage 4に到達した。

Node.js側では、v18でグローバルfetchnode:test、v20で--env-file--watchが追加された。v22でfs.globutil.styleText、v24でTypeScript型ストリッピングとURLPatternのグローバル化が実現した。Node.js 24 LTSの時点で、開発時に必要だった多くのnpmパッケージが組み込み機能で代替できる。

この記事のスタンスは「標準で済むなら標準に寄せる」。依存を減らすことはバンドルサイズの削減やメンテナンスコストの低減だけでなく、サプライチェーン攻撃の対象面を直接的に減らす効果がある。

ブラウザ編

fetch: axiosの代替

MDN: Fetch API / Node.js: Global fetch

fetchは全ブラウザで標準利用可能であり、Node.js 18以降ではグローバルに利用可能(内部的にはundici)。axiosを使う主な理由だった「ブラウザ/Node両対応」は、もはや標準だけで成立する。

// axios
const res = await axios.get("/api/users", { params: { page: 1 } });
const users = res.data;

// fetch (標準)
const res = await fetch("/api/users?" + new URLSearchParams({ page: "1" }));
const users = await res.json();

タイムアウトはAbortSignal.timeout() (MDN)で簡潔に書ける(2024年に主要ブラウザ対応済み)。

// axios
await axios.get("/api/data", { timeout: 5000 });

// fetch + AbortSignal.timeout
await fetch("/api/data", { signal: AbortSignal.timeout(5000) });

複数のシグナルを組み合わせたい場合はAbortSignal.any()(同じく2024年対応済み)を使う。

const controller = new AbortController();
const signal = AbortSignal.any([controller.signal, AbortSignal.timeout(5000)]);
await fetch("/api/data", { signal });
// 手動キャンセルもタイムアウトも両方効く

ただし、リクエスト/レスポンスのインターセプターや自動リトライ、進捗イベントはfetchにない。これらが必要ならaxiosか、より軽量なky(~2KB)を検討する。単純なAPI呼び出しならfetchで十分。

structuredClone: lodash.cloneDeep / deepmergeの代替

MDN: structuredClone() / Node.js: structuredClone()

structuredClone()は全ブラウザ・Node.js 17以降で標準利用可能。ディープコピーが1行で書ける。

// lodash
import cloneDeep from "lodash/cloneDeep";
const copy = cloneDeep(original);

// 標準
const copy = structuredClone(original);

ただし、関数やDOMノード、Errorオブジェクト、プロトタイプチェーンはコピーできない。クラスインスタンスのコピーにはlodashが引き続き必要。JSONシリアライズ可能なデータ構造であればstructuredCloneで十分。

crypto.randomUUID: uuidパッケージの代替

MDN: Crypto.randomUUID() / Node.js: crypto.randomUUID()

crypto.randomUUID()はv4 UUIDを生成する。ブラウザとNode.js 19以降で利用可能。

// uuid パッケージ
import { v4 as uuidv4 } from "uuid";
const id = uuidv4();

// 標準
const id = crypto.randomUUID();

ただし、v4 UUID以外(v1, v5, v7等)が必要な場合はuuidパッケージが必要。v4だけなら標準で十分。

URLSearchParams: query-stringの代替

MDN: URLSearchParams / Node.js: URLSearchParams

URLSearchParamsは全ブラウザ・Node.jsで標準利用可能。

// query-string
import queryString from "query-string";
const parsed = queryString.parse("?foo=bar&baz=1");
const str = queryString.stringify({ foo: "bar", baz: 1 });

// 標準
const parsed = Object.fromEntries(new URLSearchParams("?foo=bar&baz=1"));
const str = new URLSearchParams({ foo: "bar", baz: "1" }).toString();

ただし、URLSearchParamsは配列値の扱いがquery-stringと異なる(foo=1&foo=2の場合、getAll("foo")を使う必要がある)。複雑なクエリ文字列の解析が必要でなければ標準で十分。

Object.groupBy / Map.groupBy: lodash.groupByの代替

MDN: Object.groupBy()

Object.groupByはES2024で標準化され、主要ブラウザで利用可能になった。

// lodash
import groupBy from "lodash/groupBy";
const grouped = groupBy(users, (u) => u.role);

// 標準
const grouped = Object.groupBy(users, (u) => u.role);

キーにオブジェクトを使いたい場合はMap.groupByを使う。

Setメソッド: 手動実装やlodashの代替

MDN: Set

ES2025でSetに数学的な集合演算メソッドが追加され、主要ブラウザで利用可能になった。

const a = new Set([1, 2, 3, 4]);
const b = new Set([3, 4, 5, 6]);

a.intersection(b); // Set {3, 4}
a.union(b); // Set {1, 2, 3, 4, 5, 6}
a.difference(b); // Set {1, 2}
a.symmetricDifference(b); // Set {1, 2, 5, 6}
a.isSubsetOf(b); // false
a.isSupersetOf(b); // false
a.isDisjointFrom(b); // false

以前は[...a].filter(x => b.has(x))のような手動実装やlodashの_.intersectionが必要だったが、ネイティブで高速に動作する。

Iteratorヘルパー: lodash系チェーンの代替

MDN: Iterator helpers

ES2025のIteratorヘルパー(2025年3月に主要ブラウザ対応済み)で、遅延評価のチェーン処理が標準で書ける。

// lodash chain
import _ from "lodash";
const result = _(users)
	.filter((u) => u.active)
	.map((u) => u.name)
	.take(5)
	.value();

// Iterator helpers (遅延評価)
const result = users
	.values()
	.filter((u) => u.active)
	.map((u) => u.name)
	.take(5)
	.toArray();

Iterator.from()でジェネレータや任意のiterableにも使える。大量データの処理で中間配列を作らないため、メモリ効率がよい。

Temporal: moment/dayjsの代替

MDN: Temporal / TC39: proposal-temporal

2026年3月にTC39 Stage 4に到達し、Chrome 144+とFirefox 139+でネイティブサポートされた。日付・時刻の不変(immutable)な操作が標準で可能になる。

// moment
import moment from "moment";
const now = moment();
const tomorrow = now.clone().add(1, "day");
const formatted = tomorrow.format("YYYY-MM-DD");

// Temporal (標準)
const now = Temporal.Now.plainDateTimeISO();
const tomorrow = now.add({ days: 1 });
const formatted = tomorrow.toPlainDate().toString(); // "2026-04-07"
// タイムゾーン対応
const tokyo = Temporal.Now.zonedDateTimeISO("Asia/Tokyo");
const ny = tokyo.withTimeZone("America/New_York");

// 期間の計算
const start = Temporal.PlainDate.from("2026-01-01");
const end = Temporal.PlainDate.from("2026-04-06");
const duration = start.until(end); // P3M5D (3ヶ月5日)

ただし、SafariとEdgeではまだフラグ付きのため、プロダクションではpolyfill(temporal-polyfill)との併用を推奨する。ブラウザがネイティブ対応していればpolyfillはスキップされる。全ブラウザでの安定利用は2026年後半の見込み。

URLPattern: path-to-regexpの代替

MDN: URLPattern / Node.js: URLPattern

URLPatternは2025年9月に主要ブラウザで対応済み。Node.js 24ではグローバルに利用可能。

// path-to-regexp
import { match } from "path-to-regexp";
const fn = match("/users/:id");
const result = fn("/users/123"); // { params: { id: "123" } }

// URLPattern (標準)
const pattern = new URLPattern({ pathname: "/users/:id" });
const result = pattern.exec({ pathname: "/users/123" });
const id = result?.pathname.groups.id; // "123"

フレームワークなしでルーティングを実装する場合や、Service Worker内でのリクエストマッチングに有用。

Node.js編

グローバルfetch: node-fetchの代替

Node.js: Global fetch

Node.js 18以降、fetchはグローバルに利用可能(内部的にundiciベース)。

// node-fetch (以前)
import fetch from "node-fetch";
const res = await fetch("https://api.example.com/data");

// Node.js 18+ (インポート不要)
const res = await fetch("https://api.example.com/data");
const data = await res.json();

node-fetchパッケージはもう不要。ただし、undici固有の高度な機能(接続プール制御、HTTP/2等)が必要な場合はimport { request } from "undici"を直接使う。

node:test: Jest/Mocha/Vitestの代替候補

Node.js: Test runner

Node.js 18以降で安定。ゼロ依存のテストランナーがnode:testで利用可能。

import { describe, it, mock, beforeEach } from "node:test";
import assert from "node:assert/strict";

describe("Calculator", () => {
	it("adds two numbers", () => {
		assert.strictEqual(1 + 2, 3);
	});

	it("supports mocking", () => {
		const fn = mock.fn((x: number) => x * 2);
		assert.strictEqual(fn(3), 6);
		assert.strictEqual(fn.mock.callCount(), 1);
	});
});
# 実行
node --test

# カバレッジ付き
node --test --experimental-test-coverage

# watchモード (Node.js 23+)
node --test --watch

ライブラリやCLIツール、バックエンドのユニットテストに向いている。依存ゼロのためCI高速化やDockerイメージの軽量化に有効。ただし、スナップショットテストや豊富なマッチャー、UIモード、ブラウザテストが必要ならVitest/Jestに優位性がある。新規のNode.jsライブラリ開発ではnode:testを第一候補に検討する価値がある。

--watch: nodemonの代替

Node.js: --watch

Node.js 18.11以降で--watchフラグが利用可能(Node.js 22+で安定)。

# nodemon
npx nodemon server.ts

# Node.js 標準
node --watch server.ts

特定のパスだけを監視する場合は--watch-pathを使う。

node --watch-path=./src --watch-path=./config server.ts

ただし、.nodemonrcによる細かい設定(ignore, delay, ext指定等)が必要ならnodemonに優位性がある。シンプルな再起動だけなら--watchで十分。

--env-file: dotenvの代替

Node.js: --env-file

Node.js 20.6以降で--env-fileフラグが利用可能。

# dotenv (コード内でimport)
# import "dotenv/config";
# node server.js

# Node.js 標準 (コード変更不要)
node --env-file=.env server.js

# 複数ファイル対応
node --env-file=.env --env-file=.env.local server.js

アプリケーションコードにdotenvのインポートが不要になり、package.jsonのスクリプトに書くだけでよい。

package.json

{
  "scripts": {
    "dev": "node --env-file=.env --watch server.ts"
  }
}

fs.glob: globパッケージの代替

Node.js: fs.promises.glob()

fs.globfs.promises.globはNode.js 22.0で追加され、22.17 LTSで安定した。

// glob パッケージ
import { glob } from "glob";
const files = await glob("src/**/*.ts");

// Node.js 標準
import { glob } from "node:fs/promises";
const files = [];
for await (const entry of glob("src/**/*.ts")) {
	files.push(entry);
}

標準のfs.globAsyncIterableを返すため、配列で欲しい場合はfor await...ofで収集する必要がある。globパッケージのようなoption(ignore等)のサポートは限定的だが、シンプルなパターンマッチなら標準で十分。

fs.rm: rimrafの代替

Node.js: fs.promises.rm()

fs.rm{ recursive: true, force: true }オプションでディレクトリの再帰削除ができる(Node.js 14.14以降)。

// rimraf
import { rimraf } from "rimraf";
await rimraf("dist");

// Node.js 標準
import { rm } from "node:fs/promises";
await rm("dist", { recursive: true, force: true });

シェルスクリプトでも同様。

# rimraf (cross-platform rm -rf)
npx rimraf dist

# Node.js 標準
node -e "require('fs').rmSync('dist', { recursive: true, force: true })"

rimrafの存在意義だったWindows互換の再帰削除は、fs.rmで解決済み。

util.styleText: chalkの代替

Node.js: util.styleText()

util.styleTextはNode.js 20.12で追加され、22.17 LTSで安定した。

// chalk
import chalk from "chalk";
console.log(chalk.red.bold("Error:"), chalk.yellow("file not found"));

// Node.js 標準
import { styleText } from "node:util";
console.log(
	styleText(["red", "bold"], "Error:"),
	styleText("yellow", "file not found"),
);

ただし、テンプレートリテラルでの複雑なスタイリングやカスタムテーマが必要ならchalkに優位性がある。単純な色付きログ出力ならutil.styleTextで十分。

TypeScript型ストリッピング: ts-node/tsxの代替

Node.js: TypeScript support

Node.js 22.6で--experimental-strip-typesとして導入され、Node.js 24 LTSでは.tsファイルに対してデフォルトで有効になった。

# ts-node
npx ts-node src/main.ts

# tsx
npx tsx src/main.ts

# Node.js 24+ (追加パッケージ不要)
node src/main.ts

型注釈を除去するだけで、トランスパイルは行わない。enumnamespace、コンストラクタのパラメータプロパティ(public x: number)等、JavaScriptコード生成が必要な構文はランタイムエラーになる。

// ✅ 動作する
interface User {
	name: string;
	age: number;
}
const greet = (user: User): string => `Hello, ${user.name}`;

// ❌ ランタイムエラー (コード生成が必要)
enum Direction {
	Up,
	Down,
}

ただし、enumやパスエイリアス(paths)を使っている場合、またはNode.js 22以前を対象とする場合はtsxが引き続き必要になる。新規プロジェクトではenumを避けてas constを使い、Node.js標準の型ストリッピングに対応する設計を推奨する。

まとめ

2026年現在、「標準で十分」な領域は着実に広がっている。以下の表で対応関係を整理する。

従来のライブラリ標準の代替環境
axios (単純なリクエスト)fetch + AbortSignal.timeout()Browser + Node 18+
lodash.cloneDeep / deepmergestructuredCloneBrowser + Node 17+
uuid (v4)crypto.randomUUID()Browser + Node 19+
query-stringURLSearchParamsBrowser + Node
lodash.groupByObject.groupByBrowser + Node 21+
Set手動操作Set.prototype.intersectionBrowser + Node 22+
lodashチェーンIteratorヘルパーBrowser + Node 22+
moment / dayjsTemporalChrome 144+, Firefox 139+
path-to-regexpURLPatternBrowser + Node 24+
node-fetchグローバルfetchNode 18+
nodemonnode --watchNode 22+
dotenvnode --env-fileNode 20.6+
globfs.globNode 22+
rimraffs.rmNode 14.14+
chalkutil.styleTextNode 22+
ts-node / tsxnode --strip-typesNode 24+
jest / mochanode:testNode 18+

各セクションで触れたとおり、標準APIには制約もある。ただし、依存を減らすことはセキュリティ・パフォーマンス・メンテナンスすべてに効く。新規プロジェクトではまず標準APIで書き始め、足りない場合にだけライブラリを足すアプローチを推奨する。

この記事に関するIssueをGithubで作成する

Read Next