Metro — باندلر JavaScript است که بهطور ویژه برای React Native طراحی شده و به صورت پیشفرض برای ساخت اپلیکیشنهای موبایل در این پلتفرم استفاده میشود. بر خلاف باندلرهای جهانی، Metro برای منابع محدود دستگاههای موبایل بهینهسازی شده و انتگراسیون با Hermes engine و Fast Refresh را فراهم میکند. به گزارش Metro Documentation (2026)، این باندلر بیش از 90% پروژههای React Native را در جهان پردازش میکند.
نکات کلیدی
Metro یک باندلر JavaScript منبعباز است که توسط تیم Meta برای React Native ساخته شده است. آن جایگزین Packager از نسخههای اولیه React Native شد و به ابزار استاندارد ساخت برای این پلتفرم تبدیل شد. Metro برای توسعه وب طراحی نشده است: معماری آن فقط بر اپلیکیشنهای موبایل متکی است که تحت موتورهای JavaScript JSC (JavaScriptCore) یا Hermes کار میکنند.
Metro در سال 2018 به عنوان جایگزین React Native Packager قدیمی معرفی شد. دلیل اصلی ایجاد آن نیاز به یک باندلر بود که با میلیونها مدول در اپلیکیشنهای موبایل بزرگ به صورت مؤثر کار کند. بر خلاف Webpack، Metro از CSS، HTML یا تصاویر به عنوان مدول پشتیبانی نمیکند — این منابع توسط ابزارهای جداگانه React Native پردازش میشوند. Facebook از Metro برای ساخت اپلیکیشن اصلی خود استفاده میکند که بیش از 100 هزار فایل دارد.
Metro از طریق npm به عنوان بسته metro منتشر میشود و همراه با React Native CLI به صورت خودکار نصب میشود. نسخه Metro به نسخه React Native وابسته است، بنابراین بهروزرسانی باندلر همراه با بهروزرسانی پلتفرم انجام میشود.
Metro نقطه ورودی اپلیکیشن را دریافت میکند، گراف وابستگی را میسازد، هر مدول را تبدیل میکند و نتیجه را به یک باندل واحد سریالی میکند. فرآیند از سه مرحله عبور میکند: Resolve (حل مدولها)، Transform (تبدیل) و Serialize (سریالیسازی).
// نمونه پیکربندی Metro برای تبدیل سفارشی
const metroConfig = {
transformer: {
babelTransformerPath: require('metro-babel-transformer'),
async transform({ src, filename, options }) {
const result = await babelTransform({ src, filename, options });
return {
ast: result.ast,
code: result.code,
map: result.map,
dependencies: [],
};
},
},
serializer: {
createModuleIdFactory() {
let nextId = 0;
const moduleIds = new Map();
return ({ path }) => {
if (!moduleIds.has(path)) {
moduleIds.set(path, nextId++);
}
return moduleIds.get(path);
};
},
},
};
در مرحله Resolve، Metro مکان هر مدول وارداتی را با توجه به الیاسها و node_modules تعیین میکند. در مرحله Transform، هر فایل برای تبدیل JSX، TypeScript و سایر افزونهها به JavaScript خالص از Babel transformer عبور میکند. مرحله نهایی Serialize تمام مدولهای تبدیل شده را در یک یا چند فایل باندل جمع آوری میکند.
Metro بر روی معماری مدولار ساخته شده است که هر مرحله کامپایل به عنوان یک کامپوننت جداگانه پیادهسازی شده است. این امکان جایگزینی مدولهای استاندارد با مدولهای سفارشی بدون تغییر هسته باندلر را فراهم میکند. معماری Metro شامل سه بسته اصلی است: metro، metro-config و metro-resolver.
Metro Server — سرور توسعه که با دستور npx react-native start راهاندازی میشود. آن درخواستهای تبدیل مدول را در زمان واقعی پیشخوانی کرده و Fast Refresh را فراهم میکند. Module Store — کش است که مدولهای تبدیل شده را در حافظه برای سرعت بخشیدن کامپایلهای مجدد ذخیره میکند. Dependency Graph — گراف وابستگی که با تغییر فایلها به صورت افزایشی بهروز میشود.
Watchman — ناظر فایل از Meta که Metro برای تشخیص تغییرات در سیستم فایل استفاده میکند. بدون Watchman، Metro مجبور است در هر تغییر کل ساختار فایل را مجدداً اسکن کند که به طور قابل توجهی توسعه را کند میکند. نصب Watchman برای کار راحت با Metro در پروژههای هر اندازهای ضروری است.
پیکربندی Metro در فایل metro.config.js در ریشه پروژه تعیین میشود. یک فایل پیکربندی طیپی پوشههای اضافه برای جستجوی مدولها، بلوکهایی برای حذف فایلهای غیرضروری و ترانسفورمرهای سفارشی تعیین میکند. در React Native 0.72+ از تشخیص خودکار پیکربندی استفاده میشود، اما برای مونوریپوزیتوریها پیکربندی ضروری است.
// metro.config.js
const config = {
resolver: {
sourceExts: ['js', 'jsx', 'ts', 'tsx', 'json'],
nodeModulesPaths: ['node_modules'],
blockList: [/\.test\.js$/, /__tests__\/.*/],
extraNodeModules: {
'shared-components': path.resolve(__dirname, '../shared/src'),
},
},
transformer: {
minifierConfig: {
keep_classnames: true,
keep_fnames: true,
mangle: { reserved: ['React', 'Component'] },
},
},
};
module.exports = mergeConfig(getDefaultConfig(__dirname), config);
blockList فایلهای تست را از کامپایل حذف میکند و اندازه باندل را کاهش میدهد. nodeModulesPaths مسیرهای اضافه برای جستجوی بستهها را نشان میدهد — برای مونوریپوزیتوریها حیاتی است. extraNodeModules برای بستههای مشترک مورد استفاده در میان پروژههای مونوریپوزیتوری الیاس ایجاد میکند.
Metro چندین مکانیسم برای بهینهسازی اندازه باندل و سرعت کامپایل ارائه میدهد. Inline Requires — موثرترین تکنیک است که ایمپورتهای سطح بالا را به require محلی داخل توابع تبدیل میکند. RAM bundles بارگیری افزایشی مدولها را ممکن میسازد. Hermes JavaScript را به بایت کد کامپایل میکند و اندازه اپلیکیشن را 20–30% کاهش میدهد.
// metro.config.js — بهینهسازی برای تولید
const config = {
transformer: {
async transform({ src, filename, options }) {
const inlineRequires = options.dev ? false : true;
return await defaultTransform({ src, filename, options: { ...options, inlineRequires } });
},
},
serializer: {
polyfillModuleNames: [],
},
};
// برای فعالسازی Hermes — در build.gradle (Android):
// project.ext.react = [enableHermes: true, bundleInRelease: true]
// برای iOS — در Podfile: :hermes_enabled => true
برای تشخیص اندازه باندل، Metro پرچم --bundle-output را با خروجی آمار ارائه میدهد. از bundle-visualizer برای تجزیه و تحلیل ترکیب باندل و پیدا کردن مدولهای بزرگی که میتوانند به صورت تنبل بارگیری شوند استفاده کنید. بررسی منظم اندازه باندل باید بخشی از خط لوله CI/CD پروژه React Native باشد.
Metro از باندلهای دلتا پشتیبانی میکند — مکانیسمی که پس از اولین کامپایل کامل، سرور فقط تغییرات (دلتا) بین نسخه قدیمی و جدید باندل را ارسال میکند. این کامپایلهای بعدی را به طور رادیکال سرعت میبخشد: زمان بهروزرسانی از چند ثانیه به دههها میلیثانیه کاهش مییابد. باندلهای دلتا به ویژه در مرحله توسعه مؤثر هستند زمانی که توسعهدهنده میتواند تغییرات را ذخیره کرده و اپلیکیشن را مجدداً بارگیری کند.
برای فعالسازی باندلهای دلتا در React Native از پرچم --delta در دستور npx react-native bundle استفاده میشود. در طرف کلینت، باندلهای دلتا از React Native 0.64 به بعد پشتیبانی میشوند. در کامپایلهای تولیدی، باندلهای دلتا اعمال نمیشوند — به جای آنها برای حداکثر عملکرد راهاندازی، از یک باندل کامل با بایت کد Hermes استفاده میشود. این به دلیل آن است که افزایش سرعت توسعه هزینه اولین کامپایل کامل را جبران میکند.
Hermes — موتور JavaScript است که توسط Meta بهطور ویژه برای React Native طراحی شده است. Metro در مرحله کامپایل بایت کد Hermes را تولید میکند که به اپلیکیشن اجازه میدهد بدون کامپایل پرهزینه JavaScript روی دستگاه راه اندازی شود. برای فعالسازی Hermes کافی است enableHermes: true را به metro.config.js اضافه کرده و build.gradle یا Podfile را پیکربندی کنید. Hermes زمان راهاندازی اپلیکیشن را 30–50% کاهش میدهد و اندازه APK را در مقایسه با JavaScriptCore 20–30% کاهش میدهد.
هنگام استفاده از Hermes، مهم است محدودیتها را در نظر داشته باشید: موتور از Proxy، Reflect و برخی امکانات ES6 پشتیبانی نمیکند. اکثر اپلیکیشنهای React Native از این امکانات به صورت مستقیم استفاده نمیکنند، اما برخی کتابخانهها ممکن است مناقضه ایجاد کنند. قبل از فعالسازی Hermes، سازگاری تمام وابستگیهای پروژه را از طریق چک لیست رسمی سازگاری بررسی کنید. Metro پس از فعالسازی Hermes به طور خودکار به حالت تولید بایت کد تبدیل میشود.
برای پیگیری کارایی کامپایل Metro، از متریکهای ساخته شده قابل دسترسی از طریق Flipper — ابزار اشکالزدایی React Native استفاده کنید. Metro رویدادهایی را منتشر میکند: bundle_request، transform، resolve با زمان اجرای هر مرحله. تجزیه و تحلیل این دادهها به شناسایی گرفتههای تنگ کمک میکند: اگر مرحله transform بیش از 70% زمان را بگیرد، مشکل در Babel transformer است. برای تشخیص جزئیاتی، سبت رویدادهای Metro را از طریق پرچم --verbose فعال کنید.
سؤالات متداول
از نظر فنی بله — پروژههای آزمایشی مانند react-native-webpack وجود دارند، اما به طور رسمی پشتیبانی نمیشوند. Metro با React Native bridge، Turbo Modules و Hermes در سطحی انتگراسیون دارد که برای Webpack قابل دسترسی نیست. جایگزینی Metro منجر به از دست رفتن Fast Refresh و پشتیبانی رسمی خواهد شد.
React Native از CSS برای سبکدهی استفاده نمیکند — به جای آن سبکدهی JavaScript از طریق StyleSheet.create اعمال میشود. از آنجایی که Metro به طور انحصاری برای React Native ساخته شده، پشتیبانی از CSS لازم نیست. برای رندر وب از طریق React Native Web، CSS توسط ابزارهای جداگانه خارج از Metro پردازش میشود.
Metro تصاویر یا فونتها را به عنوان مدول پردازش نمیکند. منابع از طریق require('./image.png') متصل میشوند، اما Metro آنها را فقط به عنوان وابستگیهای رشتهای ثبت میکند. بارگیری فعلی تصاویر توسط کد اصلی React Native از طریق کامپوننت Image انجام میشود و Metro منابع را به باندل کپی میکند.
Rollup مدولهای ES را با tree shaking در سطح مدول تولید میکند که اندازه باندل حداقل را برای کتابخانهها دارد. Metro باندل CommonJS را با تبدیل داخلی و بهینهسازی برای موتورهای موبایل تولید میکند. Rollup از Fast Refresh پشتیبانی نمیکند و نمیتواند با مدولهای اصلی React Native کار کند.
کامپایل سرد Metro به دلیل اسکن کامل node_modules کند میشود. راهحلها: watchFolders را برای مونوریپوزیتوریها اضافه کنید، از maxWorkers برای تبدیل موازی استفاده کنید و Watchman را نصب کنید. برای پروژههایی با 10 000+ فایل، metro-memory-fs را برای ذخیرهسازی در حافظه در نظر بگیرید.
نتیجهگیری
watchFolders و extraNodeModules برای حل صحیح مدولها مورد نیاز است.ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید