es-toolkit のバンドルサイズ入門:lodash と比較して最大 97% 削減する小ささの仕組みと測定方法
【免费下载链接】es-toolkitA modern JavaScript utility library that's 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit
es-toolkit は「モダンな実装による高速・軽量」を特徴とする JavaScript ユーティリティライブラリで、その中でも特に注目されるのがバンドルサイズの小ささです。本記事では、es-toolkit が lodash と比べて関数によっては最大 97% も小さいバンドルサイズを実現している背景、その具体的な比較データ、そして公式が採用している esbuild ベースの測定手法を、リポジトリ内のソースコードとベンチマーク実装に基づいて詳しく解説します。読み終えると、バンドルサイズ削減のための選択肢として es-toolkit を評価・導入するための判断材料と、自前で測定する方法を身につけられます。
es-toolkit のバンドルサイズとは
es-toolkit はモダンな JavaScript 文法と最小限の実装方針を採用しているため、同等機能を持つ lodash と比較して非常に小さなバンドルサイズを誇ります。公式ドキュメント(docs/bundle-size.md および docs/ja/bundle-size.md)では、関数によっては lodash と比べて最大 97% 小さくなると明記されており、いくつかのユーティリティ関数は100 バイト未満のサイズしかありません。
バンドルサイズは Web アプリケーションの初期ロード性能に直結する指標です。ユーティリティライブラリはプロジェクト全体で広く使われるため、1 関数あたりのサイズが小さいことは、ツリーシェイキング(未使用コードの除去)が効きにくい場面でも全体の転送量を抑える上で大きなアドバンテージになります。
バンドルサイズの比較:実際の測定データ
リポジトリ内の docs/data/bundle-size.json には、主要関数のバンドルサイズ測定結果が格納されています(測定対象はes-toolkit@1.49.0とlodash-es@4.18.1)。代表的な関数の実測値(単位はバイト)は以下のとおりです。
| 関数 | lodash-es | es-toolkit | 削減率(目安) |
|---|---|---|---|
| sample | 4,849 | 94 | 約 98% |
| difference | 7,992 | 90 | 約 99% |
| sum | 726 | 93 | 約 87% |
| debounce | 2,901 | 531 | 約 82% |
| throttle | 3,139 | 855 | 約 73% |
| pick | 9,554 | 132 | 約 99% |
| zip | 3,993 | 221 | 約 94% |
たとえばsampleは lodash の約 4.8 KB に対して es-toolkit はわずか 94 バイト、pickに至っては約 9.5 KB から 132 バイトへと激減しています。debounceやthrottleのようにタイマー管理を伴う関数でも、lodash の 1/5 〜 1/3 程度に収まっています。関数によっては 100 バイトを下回るサイズであることが、このデータからも裏付けられます。
compat パッケージとの関係
es-toolkit には lodash との完全互換を目指すes-toolkit/compatというエントリポイントもあります。互換性を優先する分、コアのes-toolkitよりは若干サイズが大きくなりますが、それでも lodash よりははるかに小さいのが実態です。
たとえば benchmarks/bundle-size/chunk.spec.ts の実測スナップショットを見ると:
| パッケージ | chunk のサイズ |
|---|---|
| lodash-es | 3,181 バイト |
| es-toolkit | 238 バイト |
| es-toolkit/compat | 552 バイト |
es-toolkit/compatでも lodash の約 1/6 のサイズに抑えられています。同様に benchmarks/bundle-size/add.spec.ts では、addが lodash-es で 1,976 バイト、es-toolkit/compatで 540 バイトと測定されています。
FP 版の比較
関数型プログラミング向けのes-toolkit/fpでも、その差はさらに顕著です。benchmarks/bundle-size/fp/chunk.spec.ts では、chunkを各ライブラリの FP 版から import したときのサイズが次のように記録されています。
| パッケージ | FP 版 chunk のサイズ |
|---|---|
| lodash/fp/chunk | 51,712 バイト |
| es-toolkit/fp | 286 バイト |
| remeda | 607 バイト |
lodash の FP 版はモジュール構成の都合で 51 KB を超えるのに対し、es-toolkit/fp は 286 バイト。remedaなどの他のモダンなライブラリと比べても遜色のない、いやむしろ小さいサイズを実現しています。
バンドルサイズの測定方法
測定ツール:esbuild 0.28.0
公式のバンドルサイズ測定はesbuild 0.28.0を使用して行われます。esbuild は高速なバンドラーであり、minify(圧縮)と bundle(依存解決込みの単一ファイル化)を組み合わせることで、「実際にその関数を import したときにブラウザへ届く実効サイズ」を正確に測ることができます。
測定に使われるコードは、docs/bundle-size.md に記載のとおり、次のような単純な import 文です。
import { chunk } from 'es-toolkit'; // または import { chunk } from 'lodash-es'; console.log(chunk);console.logで関数を参照することで、ツリーシェイキングによる除去を防ぎつつ、「その関数だけを取り込んだ場合の最終出力サイズ」を算出します。このコードはes-toolkitとlodash-esの両方で実行され、結果が比較されます。
測定の実装:getBundleSize.ts
測定の中心となる実装は benchmarks/bundle-size/utils/getBundleSize.ts にあります。このモジュールは、引数で受け取ったパッケージ名と関数名から import 文を組み立て、esbuild の API を直接呼び出してバンドル結果のバイト長を返します。
import esbuild from 'esbuild'; import path from 'path'; export async function getBundleSize( pkg: 'lodash-es' | 'es-toolkit' | 'es-toolkit/compat' | 'es-toolkit/fp' | 'remeda', funcName: string ) { const script = `import { ${funcName} } from "${pkg}"; console.log(${funcName})`; return getBundleSizeFromScript(script); } export async function getBundleSizeFromScript(script: string) { const bundled = await esbuild.build({ stdin: { contents: script, resolveDir: import.meta.dirname, sourcefile: path.resolve(import.meta.dirname, 'test.js'), loader: 'js', }, write: false, minify: true, bundle: true, }); return Buffer.from(bundled.outputFiles![0].contents).byteLength; }実装のポイントは以下のとおりです。
stdin経由でソース文字列を直接 esbuild に渡し、bundle: trueとminify: trueを指定して単一ファイルに圧縮します。write: falseによりディスクへ書き出さず、outputFilesから出力内容を取得します。- 最終的なサイズは
Buffer.byteLengthで算出されるため、UTF-8 のバイト単位の正確な値が得られます。 - 対応パッケージは型定義からもわかるように
lodash-es、es-toolkit、es-toolkit/compat、es-toolkit/fp、remedaの 5 系統です。
ベンチマークの構成と実行方法
bundle-size のベンチマークは Vitest のスナップショットテストとして実装されています。たとえば benchmarks/bundle-size/chunk.spec.ts では、lodash-es・es-toolkit・es-toolkit/compatそれぞれについてgetBundleSizeを呼び出し、期待値をインラインスナップショット(toMatchInlineSnapshot)で固定しています。
import { describe, expect, it } from 'vitest'; import { getBundleSize } from './utils/getBundleSize'; describe('chunk bundle size', () => { it('lodash-es', async () => { const bundleSize = await getBundleSize('lodash-es', 'chunk'); expect(bundleSize).toMatchInlineSnapshot(`3181`); }); it('es-toolkit', async () => { const bundleSize = await getBundleSize('es-toolkit', 'chunk'); expect(bundleSize).toMatchInlineSnapshot(`238`); }); it('es-toolkit/compat', async () => { const bundleSize = await getBundleSize('es-toolkit/compat', 'chunk'); expect(bundleSize).toMatchInlineSnapshot(`552`); }); });この構成により、バンドルサイズの「回帰」を CI で検出できます。仮に実装変更でサイズが増加した場合、スナップショットテストが失敗するため、サイズ増大を未然に防げるのです。ベンチマークの依存関係は benchmarks/package.json で管理されており、esbuildは0.28.0に固定されています。
また、benchmarks/package.json には次のような npm スクリプトが定義されています。
{ "scripts": { "bench": "vitest bench --root performance", "check-bundle-size": "vitest run --update bundle-size" } }check-bundle-sizeを実行すると、bundle-sizeディレクトリ配下の spec が走り、スナップショットが最新の測定結果で更新されます(--updateフラグ)。benchは実行時性能のベンチマーク(benchmarks/performance)を Vitest の bench モードで実行するためのものです。バンドルサイズ測定とは役割が異なる点に注意してください。
なぜこれほど小さくできるのか:実装から読み解く
小ささの理由は、src/array/chunk.ts の実装を見るとよくわかります。es-toolkit のchunkは、依存ライブラリを一切使わず、ネイティブのArrayとsliceだけで実装されています。
export function chunk<T>(arr: readonly T[], size: number): T[][] { if (!Number.isInteger(size) || size <= 0) { throw new Error('Size must be an integer greater than zero.'); } const chunkLength = Math.ceil(arr.length / size); const result: T[][] = Array(chunkLength); for (let index = 0; index < chunkLength; index++) { const start = index * size; const end = start + size; result[index] = arr.slice(start, end); } return result; }- 内部ヘルパーや polyfill への依存がなく、型定義(
.d.ts)と本体のみがバンドル対象になります。 Array(chunkLength)による事前確保とarr.slice(start, end)による分割だけという最小限のコードで、lodash が持つ多数のエッジケース処理や互換性レイヤーを省いています。- 一方、
es-toolkit/compatは lodash との挙動互換(例えばchunkの引数の柔軟な解釈など)を追加で含むため、コアよりは大きくなりますが、それでも lodash よりはるかに小さいサイズを維持しています。
この「モダンな実装=古い環境向けの互換コードを持たない」という方針が、97% 削減というバンドルサイズの数字の源泉です。
まとめ
es-toolkit は、モダンで依存の少ない実装によって、lodash と比べて関数によっては最大 97% 小さいバンドルサイズを実現しています。その裏付けとして、リポジトリ内には:
- 実測データの集計(docs/data/bundle-size.json)
- esbuild 0.28.0 による測定ユーティリティ(benchmarks/bundle-size/utils/getBundleSize.ts)
- 関数ごとのスナップショットテスト(benchmarks/bundle-size 配下の各
*.spec.ts) - 実行コマンド(benchmarks/package.json の
check-bundle-size)
が整備されており、誰でも同じ手順でサイズを検証・再現できます。バンドルサイズを削減したいプロジェクトでユーティリティライブラリを選定する際には、es-toolkit(互換性が必要ならes-toolkit/compat、関数型スタイルならes-toolkit/fp)が有力な選択肢となるでしょう。
【免费下载链接】es-toolkitA modern JavaScript utility library that's 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考