پیاده سازی تکنیک Code Splitting در React

اگر سری مقالات پیکربندی webpack برای react رو مطالعه کرده باشید اونجا یک کانفیگ سراسری webpack برای کل اپلیکیشن نوشتیم و قرار بود Module Bundling رو برامون انجام بده و خروجی اپلیکیشن رو روی مرورگر و port مربوطه ببینیم.

توجه : این مقاله دنباله همون سری مقالات پیکربندی webpack و برای react هستش و قراره تغییرات جدید رو روی همون فایل ها و تنظیمات اعمال کنیم.

رفته رفته با افزایش تعداد کامپوننت ها و وسیع تر شدن اپلیکیشن خروجی webpack و bundle.js ما خیلی حجیم و سنگین میشه و در زمان run-time کاربر بایستی حجم زیادی از JS رو دانلود کنه و این خیلی برای مثلا یک فایل 5 مگابایتی یا حتی بیشتر منطقی به نظر نمیرسه و من خودم خیلی باهاش اوکی نیستم ....


react code splitting آشنایی با مفهوم
react code splitting آشنایی با مفهوم


با پیاده سازی Code Splitting شما در نهایت یک فایل main.js اصلی خواهید داشت و در کنارش کامپوننت هارو بصورت chunk های مجزا که فایل main بر حسب نیاز اونها رو لود می کنه. برای مثال : اگر یک اپلیکیشن دارید که مثلا قبلا فایل bundler.js حدود 5 مگابایت بوده الان main.js اش میشه 500 کیلوبایت و به ازای هر کامپوننت chunk file ها ایجاد میشن که مثلا هر کدوم 100 کیلوبایت یا بیشتر حجم دارن و دیگه کل اجزای اپلیکیشن داخل یک فایل جمع نمیشه.

شاید درک این قضیه براتون کمی مبهم باشه , ولی با اجرای مثال مفهومی و کاربردی این مقاله قطعا متوجه مفهوم این تکنیک میشید و خواهید دید که React همراه با Webpack و Babel چه قابلیت هایی خوبی داره و چقدر می تونید از نظر بهینه بودن روی اپلیکیشن خودتون کار کنید.

معرفی Lazy و Suspense

اگر اشتباه نکنم از نسخه 16.6 به بعد دو متد جدید به نام های lazy و suspense به React اضافه شدن که وظیفه مدیریت Dynamic Import رو در React دارن و خیلی خیلی کاربردی و مفید هم هستن. با کمک این قابلیت شما می تونید بعد از import با then به مرحله بعد برید و کارای دیگه رو انجام بدید و مفهومش مثل همون Promise و Async ها هستش ...

البته قبلا پکیج هایی مثل loadable-components قبلا وجود داشتن و این قضیه رو هندل می کردن ولی الان React بصورت built-in این قابلیت رو اضافه کرده و می تونید ازش استفاده کنید.

نکته : قابلیت های جدید lazy و suspense هنوز بصورت SSR و سمت سرور قابل استفاده نیستن و باید برای هندل کردن این مسئله از پکیج قبلی یعنی همون loadable-components استفاده کنید.

در مثال زیر یک نمونه ساده برای استفاده از lazy و suspense رو می بینید :

const Menu = React.lazy(() => import('./Menu'));
const Home = React.lazy(() => import('./Home'));
function MyComponent() {
    return (
        <div>
            <Suspense fallback={<div>Loading...</div>}>
                <Menu />
                <Home />
            </Suspense>
        </div>
    );
}

همانطورکه در کد بالا می بینید ما دو کامپوننت Home و Menu رو بصورت Dynamic در صفحه import کردیم و البته اینجا import داینامیک با کمک متد lazy انجام شده و این Syntax رو حتما رعایت کنید.

در پایین هم یک functional-component به نام MyComponent هستش که بعد از تگ div اصلی یک Suspense رو نوشتیم که یک prop به اسم fallback میگیره و تا زمانیکه اون دوتا کامپوننت لود نشد fallback شما Loading رو نشون میده. تفاوت fallback و callback هم پس الان متوجه شدید ...

نصب پکیج های مربوطه و تنظیمات webpack و babel

همه کار نحوه import کردن کامپوننت ها نیست و باید روی webpack و babel یکسری تغییرات اعمال کنیم که dynamic import ها پشتیبانی بشن و بتونیم code splitting رو پیاده سازی کنیم. اولین کار نصب پکیج زیر برای babel هستش و اعمال تغییرات در فایل babelrc. که کانفیگ های پروژه هستش :

 npm install --save-dev @babel/plugin-syntax-dynamic-import 

حالا برای اعمال تغییرات جدید فایل کانفیگ babelrc. به این شکل تغییر بدید و plugin رو اضافه کنید :

{
    "plugins": ["@babel/plugin-syntax-dynamic-import"]
}

بعد از اضافه کردن قابلیت dynamic import به babel باید تغییرات زیر رو هم به webpack اعمال کنید :

...
entry: path.resolve(__dirname, 'src/index.js'),
output: {
        filename: 'main.js',
        chunkFilename: '[chunkhash].js',
        path: path.resolve(__dirname, 'build')
}
...

یعنی اینجا اومدیم entry رو برای webpack همون فایل index.js در نظر گرفتیم ولی با کمی تفاوت مقدار output رو عوض کردیم. filename رو برابر با main.js گذاشتیم که اسکریپت های اصلی برنامه مثل خود react و react-dom و غیره هستش و chunkFilename هم کامپوننت های import شده هستن که با کمک chunkhash یک اسم random و hash شده بهشون نسبت داده میشه. مقدار path هم خروجی پروژه برای build گرفتن هستش که ما همون فولدر build رو در نظر گرفتیم.

خوب حالا دستور build رو که بزنید در داخل فولدر build یک فایل main.js دارید و یکسری فایل JS با اسم hash شده که به اصطلاح همون chunk file ها هستن و اگر سورس هاشون رو چک کنید محتوای کامپوننت شما رو دارن و در داخل فایل main.js هیچ اثری ازشون نیست بجز اسمشون برای اعمال dynamic import ها بصورت خودکار توسط module bundler و بقیه ماجرا ....


تا مقالات بعدی و آموزش های جدید خدانگهدار

موفق باشید