مقدمه
در دنیای توسعه نرمافزار، مدیریت وابستگیها (Dependencies) یکی از جنبههای کلیدی در ایجاد پروژههای کارآمد و امن است. در چارچوب داتنت، بستههای نوگت (NuGet Packages) نقش مهمی در تأمین کتابخانهها و ابزارهای مورد نیاز پروژهها ایفا میکنند. با این حال، در نسخههای قدیمیتر داتنت، فرآیند بازسازی (Restore) پروژهها شامل تمامی مراجع بستههای ارائهشده توسط چارچوب بود، حتی آنهایی که در پروژه استفاده نمیشدند. این موضوع نه تنها زمان بازسازی و ساخت (Build) پروژه را افزایش میداد، بلکه احتمال بروز خطاهای کاذب در ابزارهای امنیتی مانند نوگت آدیت (NuGet Audit) را نیز بالا میبرد. با معرفی داتنت 10، قابلیت جدیدی به نام هرس کردن بستهها (Package Pruning) به صورت خودکار ارائه شده است که این مشکلات را برطرف میکند. این مقاله به بررسی مفهوم هرس کردن مراجع بستههای ارائهشده توسط چارچوب، نحوه عملکرد آن، مزایا و چگونگی استفاده از آن در پروژههای داتنت میپردازد.
هرس کردن بستهها چیست و چرا اهمیت دارد؟
هرس کردن بستهها (Package Pruning) فرآیندی است که در آن مراجع بستههای نوگت ارائهشده توسط چارچوب، که در پروژه استفاده نمیشوند، به طور خودکار از گراف وابستگیها (Dependency Graph) حذف میشوند. در نسخههای قبلی داتنت، هنگام بازسازی پروژه، تمامی بستههای تعریفشده در چارچوب، حتی اگر در کد پروژه استفاده نمیشدند، دانلود و در فایل .deps.json گنجانده میشدند. این فایل حاوی اطلاعاتی درباره وابستگیهای پروژه است و وجود بستههای غیرضروری در آن میتوانست مشکلات متعددی ایجاد کند.
یکی از مشکلات اصلی، افزایش زمان بازسازی پروژه بود. دانلود و پردازش بستههای غیرضروری باعث کند شدن فرآیند ساخت پروژه میشد، بهویژه در پروژههای بزرگ یا در محیطهای یکپارچهسازی مداوم (CI/CD). علاوه بر این، وجود بستههای غیرضروری در فایل .deps.json میتوانست باعث شناسایی خطاهای کاذب توسط ابزارهای امنیتی مانند نوگت آدیت شود. این ابزارها ممکن بود بستههای استفادهنشده را به اشتباه به عنوان منبعی برای آسیبپذیریهای امنیتی شناسایی کنند، که این امر فرآیند بررسی امنیتی را پیچیدهتر میکرد.
هرس کردن بستهها در داتنت 10 این مشکلات را با حذف خودکار بستههای غیرضروری از گراف وابستگیها حل میکند. این قابلیت به طور پیشفرض برای پروژههایی که چارچوبهای داتنت 8.0، داتنت 10 و استاندارد داتنت 2.0 یا بالاتر (NET Standard 2.0+) را هدف قرار میدهند، فعال است. این ویژگی نه تنها عملکرد پروژه را بهبود میبخشد، بلکه به توسعهدهندگان کمک میکند تا پروژههایی تمیزتر و امنتر ایجاد کنند.
نحوه عملکرد هرس کردن بستهها
هرس کردن بستهها در فرآیند بازسازی پروژه انجام میشود. هنگامی که یک پروژه ساخته میشود، نوگت ابتدا گراف وابستگیها را بررسی میکند تا مشخص کند کدام بستهها واقعاً مورد نیاز هستند. بستههای ارائهشده توسط چارچوب، مانند System.Text.Json، که در نسخههای جدید داتنت به صورت داخلی در دسترس هستند، در صورت عدم استفاده در کد پروژه، از گراف حذف میشوند. این فرآیند به طور خاص برای بستههای انتقالی (Transitive Packages) اعمال میشود، یعنی بستههایی که به صورت غیرمستقیم از طریق سایر بستهها یا پروژهها به پروژه اضافه شدهاند.
برای مثال، فرض کنید پروژهای دارید که از بسته System.Text.Json نسخه 8.0.0 استفاده میکند، در حالی که این پروژه چارچوب داتنت 9 را هدف قرار داده است. از آنجا که System.Text.Json به صورت داخلی در چارچوب داتنت 9 موجود است، نیازی به دانلود این بسته به عنوان یک وابستگی خارجی نیست. در این حالت، قابلیت هرس کردن بستهها تشخیص میدهد که این بسته غیرضروری است و آن را از فرآیند بازسازی حذف میکند. این کار نه تنها حجم فایل .deps.json را کاهش میدهد، بلکه زمان لازم برای بازسازی پروژه را نیز کوتاهتر میکند.
هنگامی که یک بسته هرس میشود، پیامی با سطح جزئیات بالا (Detailed Verbosity) در خروجی فرآیند بازسازی نمایش داده میشود که نشان میدهد کدام بسته برای کدام چارچوب هدف حذف شده است. این شفافیت به توسعهدهندگان کمک میکند تا درک بهتری از فرآیند داشته باشند و در صورت نیاز، تنظیمات پروژه را تغییر دهند.
غیرفعال کردن هرس کردن بستهها
اگرچه هرس کردن بستهها به طور پیشفرض فعال است، توسعهدهندگان میتوانند در صورت نیاز آن را غیرفعال کنند. این کار با افزودن ویژگی RestoreEnablePackagePruning به فایل پروژه (.csproj) و تنظیم آن به false انجام میشود. کد زیر نشاندهنده نحوه غیرفعال کردن این قابلیت است:
<PropertyGroup>
<RestoreEnablePackagePruning>false</RestoreEnablePackagePruning>
</PropertyGroup>
این تنظیم ممکن است در مواردی مفید باشد که توسعهدهندگان بخواهند رفتار قدیمیتر داتنت را حفظ کنند یا به دلایلی خاص نیاز به حفظ تمامی بستهها، حتی بستههای غیرضروری، داشته باشند. با این حال، توصیه میشود که این قابلیت به طور پیشفرض فعال باقی بماند، زیرا مزایای آن در بهینهسازی عملکرد و امنیت پروژهها قابل توجه است.
مزایای هرس کردن بستهها
هرس کردن بستهها مزایای متعددی برای توسعهدهندگان داتنت ارائه میدهد.
- اولین مزیت، کاهش زمان بازسازی و ساخت پروژه است. با حذف بستههای غیرضروری، فرآیند دانلود و پردازش وابستگیها سریعتر انجام میشود، که این امر بهویژه در محیطهای یکپارچهسازی مداوم که پروژهها بارها ساخته میشوند، اهمیت زیادی دارد.
- دومین مزیت، کاهش خطاهای کاذب در ابزارهای امنیتی است. ابزارهایی مانند نوگت آدیت برای شناسایی آسیبپذیریهای امنیتی در بستههای پروژه استفاده میشوند. وجود بستههای غیرضروری میتواند باعث شود که این ابزارها به اشتباه آسیبپذیریهایی را گزارش کنند که در واقع تأثیری بر پروژه ندارند. هرس کردن بستهها این مشکل را با حذف بستههای استفادهنشده از گراف وابستگیها برطرف میکند.
- سومین مزیت، تمیزتر شدن فایل .deps.json است. این فایل که حاوی اطلاعات مربوط به وابستگیهای پروژه است، با حذف بستههای غیرضروری سادهتر و خواناتر میشود. این موضوع به توسعهدهندگان کمک میکند تا مدیریت وابستگیها را با دقت بیشتری انجام دهند و مشکلات احتمالی را سریعتر شناسایی کنند.
ارتباط با سایر مفاهیم داتنت
هرس کردن بستهها با سایر ویژگیهای نوگت و داتنت، مانند قفل فایل (Lock File) و حالت قفلشده (Locked Mode)، ارتباط نزدیکی دارد. فایل قفل (.lock) برای اطمینان از بازسازی یکنواخت و قابل پیشبینی پروژهها استفاده میشود. هنگامی که هرس کردن بستهها فعال است، فایل قفل بهروز میشود تا تغییرات در گراف وابستگیها را منعکس کند. در حالت قفلشده، که با تنظیم RestoreLockedMode به true فعال میشود، نوگت از تغییر خودکار وابستگیها جلوگیری میکند و تنها بستههای مشخصشده در فایل قفل را بازسازی میکند. این ویژگیها در کنار هرس کردن بستهها، به توسعهدهندگان امکان میدهند تا کنترل بیشتری بر فرآیند بازسازی داشته باشند.
مثال عملی
برای درک بهتر، فرض کنید پروژهای با چارچوب هدف داتنت 10 دارید که از بسته Microsoft.Extensions.Logging.Abstractions استفاده میکند. این بسته در چارچوب داتنت 10 به صورت داخلی موجود است، بنابراین نیازی به افزودن آن به عنوان یک وابستگی خارجی نیست. با فعال بودن هرس کردن بستهها، نوگت این بسته را از گراف وابستگیها حذف میکند و فرآیند بازسازی را سریعتر میکند. اگر توسعهدهنده بخواهد این بسته را به طور صریح حفظ کند، میتواند ویژگی RestoreEnablePackagePruning را به false تنظیم کند، اما این کار معمولاً توصیه نمیشود، مگر در موارد خاص.
نتیجهگیری
هرس کردن مراجع بستههای ارائهشده توسط چارچوب در داتنت 10 یک پیشرفت قابل توجه در مدیریت وابستگیها و بهینهسازی پروژههای داتنت است. این قابلیت با حذف خودکار بستههای غیرضروری، زمان بازسازی و ساخت پروژه را کاهش میدهد، خطاهای کاذب در ابزارهای امنیتی را به حداقل میرساند و فایلهای وابستگی را تمیزتر و خواناتر میکند. توسعهدهندگان میتوانند با استفاده از این ویژگی، پروژههایی کارآمدتر و امنتر ایجاد کنند، در حالی که همچنان انعطافپذیری لازم برای غیرفعال کردن آن در صورت نیاز را دارند. با توجه به اهمیت عملکرد و امنیت در توسعه نرمافزار، هرس کردن بستهها به عنوان یک ابزار قدرتمند در جعبهابزار توسعهدهندگان داتنت، جایگاه ویژهای دارد.