کوچیک کردن تسکهای Azure Pipelines با esbuild
خلاصهٔ کاملتر
تو وبلاگ مهندسی Azure DevOps اومده که یه تسک داخلی Azure Pipelines رو با esbuild به یه فایل جاوااسکریپت باندلشده تبدیل کردن. بستهٔ هر تسک از دهها مگابایت و هزاران فایل رسیده به سه فایل: script.js، task.json و icon.png. به گفتهٔ نویسندهها کل کار حدود ۲۰ خط ابزار بیلد بوده.
چرا حجم بسته اینقدر مهمه؟ چون ایجنت تو مرحلهٔ Initialize job، قبل از اینکه حتی یه خط از کد تسک اجرا شه، زیپ تسک رو دانلود و اکسترکت میکنه؛ اونم تو هر جاب، روی هر ایجنت و برای هر تسک. روی ایجنتهای میزبانیشده که از یه VM تمیز شروع میشن هیچ کشی هم نیست که نجاتت بده. مشکل اصلی هم حجم نیست، تعداد فایلهای ریزه: زیپ و آنزیپ کردن هزاران فایل کوچیک گرونه.
نویسندهها میگن باندلینگ و tree-shaking فقط مال فرانتاند نیست. تسک پایپلاین هم یه آرتیفکت توزیعشدهست که روزی هزاران بار از صفر دانلود و باز میشه؛ فرقش با مرورگر فقط اینه که اینجا ایجنت بیلد هزینه رو میده. همین منطق برای CLIهای npm، پکیجهای serverless و لایههای ایمیج کانتینر هم صادقه. راهحل یه استپ سادهی esbuild ـه و بعدش کافیه فیلد اجرای task.json رو به script.js وصل کنی:
await esbuild.build({
entryPoints: ["Tasks/MyTask/index.ts"],
outfile: "Tasks/MyTask/script.js",
bundle: true,
treeShaking: true,
platform: "node",
target: "node20",
format: "cjs"
});دوتا تله هم سر راه بوده. اول اینکه اگه یه پکیج هم تو Common/node_modules باشه هم تو node_modules خود تسک، esbuild دو نسخهٔ جدا ازش باندل میکنه؛ برای کتابخونههای استیتدار مثل azure-pipelines-task-lib یعنی استیت بین دو نسخه تقسیم میشه و بیصدا از بین میره. با یه پلاگین resolver کوچیک ایمپورتها رو به یه node_modules واحد رسوندن. دوم اینکه باندلینگ عمق پوشهها رو عوض میکنه، پس خوندن فایلهای کناری با __dirname باید اصلاح شه.
عددها: میانگین زمان انتقال فایل تسک از ~۱.۳۵ ثانیه به ~۰.۲۳ ثانیه رسیده و دانلودهای بالای ۱۰ ثانیه حدود ۹۸٪ کم شدن. سمت ایجنت، دانلود و اکسترکت هر تسک از ~۴.۵ ثانیه به ~۰.۲۵ ثانیه اومده (۹۴٪ کمتر) و برای دو تسک تو یه جاب میشه ~۱۷ برابر سریعتر. مصرفکنندههای تسک هم هیچ تغییری لازم نیست بدن.
نویسندهها چند تا هشدار هم میدن: استکتریس فایل باندلشده دیگه به سورس اصلی اشاره نمیکنه (با sourcemap حلش کن)، requireهای داینامیک ممکنه بشکنن پس حتماً تست کن، و چون V8 کل فایل رو یهجا لود میکنه مصرف حافظه میتونه بالاتر بره.
نکات کلیدی:
- هر جاب، بستهٔ تسک رو از صفر دانلود و اکسترکت میکنه؛ هزاران فایل ریز این مرحله رو کند میکنه
- باندل + tree-shaking با esbuild هر تسک رو به سه فایل میرسونه
- دانلود و اکسترکت هر تسک ~۴.۵ ثانیه به ~۰.۲۵ ثانیه، و دانلودهای کند ۹۸٪ کمتر
- مواظب ماژولهای استیتدار تکراری و مسیرهای __dirname باش
- هزینهش: دیباگ سختتر، ریسک require داینامیک و حافظهٔ بیشتر موقع استارت




