چطور Baseline کمک می‌کند JavaScript کمتری بفرستیم؟

چطور Baseline کمک می‌کند JavaScript کمتری بفرستیم؟

شهریور ۱۶, ۱۴۰۵

فاصلهٔ «کتابخانه» و «خود مرورگر» کوتاه‌تر شده

خیلی از وابستگی‌های package.json وقتی نصب شدند کار می‌کردند، تست‌ها سبز ماندند، و دیگر کسی سراغ‌شان نرفت. در همین مدت پلتفرم وب جلو رفت: فرمت تاریخ و عدد، درخواست HTTP، مودال، تولتیپ، deep clone و گروه‌بندی آرایه دیگر لزوماً به کتابخانه نیاز ندارند.

در یک اپ متوسط جاوااسکریپت، معمولاً حدود ۶۰ تا ۹۰ کیلوبایت (minified و gzipped) وابستگی هست که خود مرورگر الان می‌تواند پوشش بدهد. مشکل تنبلی نیست؛ تیم‌ها معمولاً روی cadence مربوط به Baseline دوباره audit نمی‌کنند.

حذف وابستگی‌های npm بعد از جایگزینی با قابلیت‌های پلتفرم

Baseline چیست؟

Baseline از WebDX Community Group می‌گوید یک قابلیت وب چقدر در Chrome، Edge، Firefox و Safari امن است:

  • Limited availability — هنوز در همهٔ موتورهای اصلی نیست؛ بدون fallback تکیه نکنید.
  • Baseline Newly available — تازه در همهٔ موتورها آمده؛ برای کاربران به‌روز خوب است، روی دستگاه‌های قدیمی‌تر ممکن است نباشد.
  • Baseline Widely available — حدود ۳۰ ماه در همهٔ موتورها بوده؛ معمولاً بدون نگرانی می‌شود سراغش رفت.

فاصلهٔ Newly تا Widely مهم است: Widely را معمولاً همین امروز می‌توان جایگزین کتابخانه کرد؛ Newly را فقط بعد از چک مخاطب یا با feature check.

وضعیت هر قابلیت را در webstatus.dev، روی MDN، یا با پکیج web-features ببینید.

قبل از حذف: سه سؤال

  1. جایگزین برای مخاطب من Baseline-safe است؟ Widely معمولاً بله. Newly را با analytics یا browserslist چک کنید.
  2. هزینهٔ واقعی جابه‌جایی چقدر است؟ اگر polyfill از خود کتابخانه سنگین‌تر شود، باندل بزرگ‌تر می‌شود (مگر conditional load).
  3. قابلیت پلتفرم همان use case واقعی من را پوشش می‌دهد؟ مثلاً axios فقط fetch نیست؛ interceptor و retry هم دارد.

هر کلاستر پایین همان سه سؤال است روی یک گوشه از وابستگی‌ها.


کلاستر ۱: بین‌المللی‌سازی (معمولاً بزرگ‌ترین برد امروز)

خانوادهٔ Intl خیلی از کتابخانه‌های کوچک فرمت را بی‌نیاز کرده است. مجموع تقریبی مجموعهٔ کامل: ~۱۴KB gzip.

کتابخانه جایگزین پلتفرم کاربرد کاهش تقریبی (gz) وضعیت Baseline
timeago.js Intl.RelativeTimeFormat «۳ ساعت پیش» و نسبی‌سازی زمان ~۱KB Widely
pluralize Intl.PluralRules قواعد جمع/مفرد بر اساس locale ~۲.۳KB Widely
numeral Intl.NumberFormat جداکننده هزارگان، ارز، درصد، compact ~۳.۹KB Widely
humanize-duration Intl.DurationFormat تبدیل مدت به متن خوانا ~۶.۶KB Newly (مارس ۲۰۲۵)
کمک‌های join لیست Intl.ListFormat «Alice, Bob, and Carol» چند KB Widely

نکته: RelativeTimeFormat واحد را خودش انتخاب نمی‌کند؛ اختلاف را حساب کنید و بزرگ‌ترین واحد مناسب را بدهید. برای DurationFormat روی سایت عمومی با دستگاه‌های قدیمی، یک سال دیگر صبر کنید یا feature check بگذارید.


کلاستر ۲: کلاینت‌های HTTP

کتابخانه جایگزین پلتفرم کاربرد کاهش تقریبی (gz) وضعیت Baseline
axios fetch + AbortController / AbortSignal.timeout GET/POST و timeout ~۱۷KB Widely
superagent همان درخواست HTTP عمومی ~۱۹KB Widely

fetch کمتر «خودکار» است. قبل از تعویض کورکورانه این شکاف‌ها را ببینید:

  • روی ۴۰۴/۵۰۰ reject نمی‌کند؛ باید res.ok را خودتان چک کنید.
  • interceptor ندارد (توکن auth، مدیریت ۴۰۱).
  • retry خودکار و upload progress درجهٔ اول ندارد.

اگر فقط GET/POST ساده دارید، یک wrapper نازک روی fetch معمولاً همان ~۱۷KB را پس می‌گیرد.

const res = await fetch("/api/users", {
  signal: AbortSignal.timeout(5000),
});

کلاستر ۳: UI primitives

اینجا جایگزینی‌ها اغلب حتی accessibleتر از پیاده‌سازی دستی هستند. مجموع تقریبی: ~۲۴KB gzip.

کتابخانه جایگزین پلتفرم کاربرد کاهش تقریبی (gz) وضعیت Baseline
a11y-dialog (و مشابه) <dialog> + showModal() مودال، focus، Escape، top layer ~۱.۸KB Widely
focus-trap همان <dialog> قفل فوکوس داخل مودال ~۶.۶KB Widely
body-scroll-lock CSS با :has(dialog:modal) قفل اسکرول پس‌زمینه ~۱.۳KB Widely
tippy.js (+ Popper) Popover API + CSS anchor positioning منو، تولتیپ، پنل شناور ~۱۴KB Newly (Popover از ژانویه ۲۰۲۵؛ anchor از ژانویه ۲۰۲۶)
body:has(dialog:modal) {
  overflow: hidden;
}

از dialog[open] برای قفل اسکرول استفاده نکنید؛ :modal فقط وقتی واقعاً مودال است true می‌شود (showModal()).

Anchor positioning هنوز خیلی تازه است: برای مخاطب مدرن عالی است، برای مخاطب گسترده fallback نگه دارید.


کلاستر ۴: ابزارهای Lodash

هدف «حذف کل Lodash» نیست؛ بخش‌هایی که مرورگر دارد را دیگر نفرستید. فقط clonedeep + groupby حدود ~۸KB gzip است.

کتابخانه / تابع جایگزین پلتفرم کاربرد کاهش تقریبی (gz) وضعیت Baseline
lodash.groupby Object.groupBy / Map.groupBy گروه‌بندی آرایه بر اساس کلید بخشی از ~۸KB+ Newly (مارس ۲۰۲۴ → Widely حدود اواخر ۲۰۲۶)
lodash.clonedeep structuredClone کپی عمیق دادهٔ ساده بخشی از ~۸KB+ Widely
union / intersection / difference متدهای Set عملیات مجموعه چند KB Newly (ژوئن ۲۰۲۴)
lodash.debounce / throttle — (هنوز native نیست) محدود کردن نرخ اجرا نگه دارید

structuredClone توابع، DOM node و prototype کلاس را مثل دادهٔ ساده کلون نمی‌کند؛ برای data plain معمولاً جایگزین تمیزی است.


کلاستر ۵: Temporal — الان حذف نکنید

این کلاستر نشان می‌دهد چارچوب گاهی می‌گوید صبر کنید.

کتابخانه فعلی جایگزین پیشنهادی کاربرد هزینهٔ تقریبی وضعیت
dayjs (~۳KB gz) یا date-fns Temporal + polyfill تاریخ/زمان بهتر از Date polyfill رسمی ~۴۴KB gz؛ نسخهٔ سبک‌تر ~۱۹KB gz هنوز Baseline نیست (Safari stable ندارد)

سؤال ۱ و ۲ اینجا رد می‌شوند: مخاطب گسترده پوشش ندارد و polyfill باندل را بزرگ‌تر می‌کند. وقتی Safari stable بیاید و به Baseline برسد، دوباره سراغش بروید — ترجیحاً با بارگذاری شرطی polyfill.


چطور روی package.json خودتان audit کنید؟

بررسی اندازهٔ پکیج در Bundlephobia

  1. وابستگی‌های production را لیست کنید: npm ls --omit=dev --depth=0
  2. هزینه را اندازه بگیرید: Bundlephobia برای عدد سریع؛ برای تصویر واقعی بعد از tree-shaking از analyzer باندل (source-map-explorer یا vite-bundle-visualizer)
  3. برای هر کاندیدا، جایگزین پلتفرم و وضعیت Baseline را در webstatus.dev یا MDN چک کنید
  4. همان سه سؤال را اجرا کنید
  5. برای Newly، در صورت نیاز progressive enhancement:
if (typeof Intl.DurationFormat === "function") {
  // پلتفرم
} else {
  // کتابخانه یا فرمت ساده‌تر
}

جمع‌بندی

کلاستر کاهش تقریبی (gzip)
بین‌المللی‌سازی ~۱۴KB
HTTP ~۱۷KB
UI primitives ~۲۴KB
Lodash (بخش‌های رایج) ~۸KB یا بیشتر
جمع معمول ~۶۰–۹۰KB

اعداد uncompressed در analyzer معمولاً دو تا سه برابر بزرگ‌ترند. بعضی پکیج‌های dialog به‌تنهایی می‌توانند تا ~۵۰KB gz باشند.

این کار یک‌باره تمام نمی‌شود. هر فصل یک audit کوچک: لیست وابستگی‌ها، چک Baseline، و برگرداندن آنچه پلتفرم دیگر خودش دارد.


این پست نسخهٔ فشرده و جدول‌محور ایده‌های مقالهٔ How Baseline Can Help You Ship Less JavaScript نوشتهٔ Jad Joubran در Smashing Magazine است؛ برای جزئیات و مثال‌های بیشتر همان منبع را ببینید. تصاویر از همان مقاله گرفته شده‌اند.