کنسول همروش ارائهدهنده سرویسهای مختلفی است که خدمات مکمل همدیگر ارائه میدهند. همانطور که در مقاله معرفی Module Federation توضیح داده شد، هدف این بود که توسعه فرانتاند هر سرویس در همروش مستقل باشد. در این مورد تلاش کردیم تا معماری Micro-Frontends بهینهای توسعه دهیم، در این مطلب خلاصه تلاش و آزمایشهای تیمفرانتاند همروش مستند شده است
روشهای مختلفی برای پیادهسازی Micro-frontends وجود دارد، یکی از رایجترین روشها استفاده از پلاگین Module Federation است که با Webpack امکان اشتراکگذاری کدها در runtime (سمت مرورگر کاربر) را ممکن میسازد. به این ترتیب شما میتوانید سرویس X را بدون بیلد مجدد سرویس Y که ارتباطی با سرویس X ندارد دیپلوی کنید در حالی که از کدهای سرویس X نیز میتوانید استفاده کنید.
تصویر بالا خلاصهشده نحوه ارتباط میکروفرانتاندهای همروش با یکدیگر است که در نهایت یک رابطکاربری واحد تحت عنوان کنسول همروش را ارائه میدهد.
پیادهسازی Module Federation با Next.js
در این راستا پلاگین module-federation/nextjs-mf توسط توسعهدهنده module-federation ساخته شده که امکان پیادهسازی معماری Micro-frontends را با حداقل دردسر در Next.js ممکن ساخته است.
برای استفاده از این پلاگین در فایل next.config.js پلاگین را در webpack اضافه کنید:
بسیار خوب، اما مشکل چه بود؟
در لحظه انجام این آزمایشها کنسول همروش یک اپ Next.js با حجم کد نسبتا زیادی بود. تخمین کد کنسول همروش 185 هزار خط کد بود که قسمتی از این کدها بدهی فنی از سالهای گذشته داشتند.
پس از تستهای متعدد و رسیدن به دمو اولیه مشکلات مختلفی وجود داشت. که در ادامه هرمورد را بررسی خواهیم کرد.
زمان بیلد: صبر ایوب
قبل از استفاده از Module Federation بیلد اپ Next.js حدود 80 تا 100 ثانیه زمان میبرد و بعد از پیادهسازی Module Federation این زمان به 3 تا 5 دقیقه افزایش پیدا کرد.
مصرف رم: “JavaScript heap out of memory”
برای بیلد اپ اصلی با استفاده از Module Federation تقریبا به 16 گیگ رم نیاز بود و این در بسته با بررسی بیشتر کلیدش پیدا نشد.
حجم bundle: “در حال بارگذاری…”
با بازکردن کنسول بیلدشده با استفاده از Module Federation در مرورگر حجم Bundle اصلی به 40 مگابایت رسیده بود و این افزایش تقریبا 900 درصدی دلیل قانعکننده و قابلحلی نداشت.
بررسی بیشتر برای حل مشکل
چیزی که مشخص بود این بود که پلاگین Module Federation و Next.js در قسمتهایی از فرآیند بیلد تسکها را به روش غیربهینهای تکرار میکنند.
این مشکل در کدبیس کنسول که نسبتا بزرگ بود پیش میآمد، در تست اولیه که یک ریپو آزمایشی با چند کامپوننت محدود بود مشکلی وجود نداشت.
حجم سرباری که بهخاطر Module Federation به بیلد اضافهشده بود بهدلیل محدودیت پیادهسازی که Webpack داشت و سربار فرآیندهای Next.js قابل حل یا بهبود نبود.
در مورد کنسول برتری Micro-frontend به فیچرهای جذاب Next.js وجود داشت. استفاده از قابلیتهای SSR و SSG در محصول کنسول محدود به صفحههای احراز هویت بود و وابستگی زیادی به Next.js وجود نداشت.
تصمیم سخت
همه اینها باعث شد تا با Next.js خداحافظی و تنها به React بسنده کنیم. با این فرض که پیچیدگیهای استفاده از Module Federation کمتر میشود و کنترل بیشتری روی پلاگینها و فرآیندهای بیلد خواهیم داشت تا مشکلهای احتمالی را بتوانیم راحتتر رهگیری و حل کنیم.
اینها مزیتهایی بودند که حین استفاده از Next.js نداشتیم، امکان اضافهکردن و کانفیگ webpack در Next.js وجود داشت اما بخشی که خود Next.js وارد عمل میشود، همان بخش مبهم و مشکلساز است.
یکی از نقاط دردآور مقابله با getServerSideProps بود، پلاگین Module Federation این بخش را تا حد خوبی راست و ریست میکند اما هزینه سربار بیلد و در نظر گرفتن این فاز باگ و مشکلات پیشبینینشده در runtime به وجود میآورد.
مسئله دیگری که نیاز به تجدیدنظر داشت Webpack بود. مشکل اینجاست که Next.js خودش در تلاش برای کنار گذاشتن Webpack است.سازنده وبپک Tobias Koppers درحالحاضر با Vercel برای توسعه Turbopack همکاری میکند. این خبر نوید این را میدهد که در آیندهای نهچندان دور مسئله کند بودن و مصرف بیشاز حد رم Next.js با Turbopack حل خواهد شد. اما درحالحاضر و احتمالا در آینده پیشرو راهحلی برای پیادهسازی Module Federation با Turbopack وجود نخواهد داشت.
منجی، Rspack آمده که Module Federation سریع و آسان باشد
آقای Zachary Jackson (سازنده Module Federation)، یکی از جدیدترین پروژههایی که در آن فعالیت دارد، Rspack است. هدف این پروژه توسعه ابزاری مشابه Webpack است، API مشابه اما با پیادهسازی بهینهتر.
وبباندلر Rspack با Rust نوشته شده و همین مزیت باعث شده در کنار بیلد سریع مصرف مموری به حداقل ممکن برسد.
پروژه Rspack فعالیت متنباز شرکت چینی ByteDance است، این شرکت نرمافزارهای اشتراکگذاری ویدیو از جمله TikTok و Douyin را توسعه میدهد.
پشتیبانی از Module Federation
پلاگین Module Federation به صورت داخلی در Rspack پیادهسازی شده و این بزرگترین چالش که افزایش مصرف رم و کاهش سرعت بیلد بود را به بهترین نحو ممکن حل میکند.
پشتیبانی از API ، لودر و پلاگینهای Webpack
یکی دیگر از مزیتهای Rspack مشابه بودن API آن به Webpack است، فایل کانفیگ Rspack شباهت زیادی به کانفیگ Webpack دارد و بیشتر پلاگینها و لودرهای پراستفاده Webpack نیز قابل استفاده هستند. این یعنی با کمترین هزینه فنی میتوانید به Rspack مهاجرت کنید و سرعت بیلد بالا و مصرف کمتر مموری را تجربه کنید.
داشتن یک ابزار بیلد براساس Rspack هم میتواند کاربردی باشد!
کانفیگ Rspack شباهت زیادی به Webpack دارد و نوشتن این کانفیگ بهدلیل وجود آپشنهای زیادی که ابزارها دارند کار سادهای نیست.
یکی از زیباییهای Vite خوانایی فایل کانفیگ آن است. در عین سادهبودن، کانفیگ Vite این امکان را میدهد که تنظیمات باندر را در صورت نیاز تغییر دهید.
سؤال اینجاست که چطور با کمترین خط کد مشابه Vite پروژه را با Rspack کانفیگ کنیم؟
توسعهدهندگان Rspack جواب این سؤال را با ابزاری بهنام Rsbuild میدهند:
از ویژگیهای Rsbuild:
- Rsbuild از Rspack بهعنوان باندلر استفاده میکند.
- کانفیگ سادهتری نسبت به Rspack دارد اما در صورت نیاز همانقدر امکان شخصیسازی به توسعهدهنده میدهد.
- همه ویژگیهایی که Rspack ارائه میدهد در مورد Rsbuild نیز صدق میکند.
در تصویر بالا زمان بیلد تعدادی کامپوننت React با باندلرهای مختلف تست شده، همین مقیاس در پروژههای بزرگتر باعث صرفهجویی زمان و بهینگی زیادی خواهد شد. اطلاعات بیشتر درباره این بنچمارک
نتیجه استفاده از Rsbuild
پس از مهاجرت به React بدون Module Federation مدت زمان بیلد پروژه اصلی (185 هزار خط کد) به کمتر از 10 ثانیه رسید و با پیادهسازی Module Federation به 30 ثانیه افزایش پیدا کرد. این درحالی است که سایر سرویسهای کنسول که حالا خودشان اپ جدایی هستند زمان بیلد 2 تا 3 ثانیه دارند.
این اتفاق باعث شد تجربه توسعه فرانتاند در همروش سریعتر شود و بهدنبال آن توسعهدهندگان فرانتاند خوشحالتری باشیم.
جدول زیر مقایسه زمانهای بیلد پروژه اصلی کنسول با استفاده و بدون استفاده از Module Federation است:
فریمورک و باندلر | بدون Module Federation | با Module Federation | ||||
زمان بیلد | حجم باندل اصلی | حداقل رم | زمان بیلد | حجم باندل اصلی | حداقل رم | |
Next.js (Webpack 5 + SWC) | 80 تا 100 ثانیه | ≈1.5 مگابایت | 8 گیگابایت | 3 تا 5 دقیقه | بیشتر از 40 مگابایت | 16 گیگابایت |
React (Rsbuild) | 7 تا 10 ثانیه | ≈1 مگابایت | 2 گیگابایت | 25 ثانیه | ≈1 مگابایت | 4 گیگابایت |