درس سیزدهم: مدیریت وابستگی‌ها با Code Splitting

Managing Dependencies with Code Splitting

23 شهریور 1399
درسنامه درس 13 از سری آموزش Webpack
02-Webpack-4-The-Complete-Tutorial-For-Beginners-lesson13

در قسمت قبل یاد گرفتیم که چطور می توانیم کدهای خود را از یکدیگر جدا کرده و درون فایل های جداگانه قرار دهیم اما در برخی از اوقات فایل های ما نیاز به پکیج ها و کتابخانه های دیگری دارند که وابستگی آن ها حساب می شوند. در چنین حالاتی باید چه کار کنیم؟ تصور کنید می خواهیم نام هر صفحه را در بالای آن صفحه نمایش بدهیم. چنین کاری نیازی به ویرایش کردن کامپوننت heading.js دارد بنابراین آن را به شکل زیر ویرایش می کنم:

import './heading.scss';

class Heading {
    render(pageName) {
        const h1 = document.createElement('h1');
        const body = document.querySelector('body');
        h1.innerHTML = 'Webpack is awesome. This is "' + pageName + '"page';
        body.appendChild(h1);
    }
}

export default Heading;

یعنی نام صفحه را به صورت یک پارامتر دریافت می کنیم تا هر صفحه بتواند نام خودش را نمایش بدهد. ما درون فایل های hello-world.js و kiwi.js از این کلاس استفاده می کنیم بنابراین باید به این کلاس ها رفته و پارامتر ورودی را به آن بدهیم. ابتدا درون فایل hello-world.js:

import HelloWorldButton from './components/hello-world-button/hello-world-button.js';
import Heading from './components/heading/heading.js';
import _ from 'lodash';

const heading = new Heading();
heading.render(_.upperFirst('hello world'));
const helloWorldButton = new HelloWorldButton();
helloWorldButton.render();

من از یکی از متدهای کتابخانه lodash استفاده کرده ام و مقدار hello world را به آن پاس داده ام. این متد حرف اول کلمات را بزرگ می کند. البته طبیعتا بزرگ کردن حرف اول کلمات به این شکل اصلا درست نیست اما برای مثال این جلسه به درد ما می خورد. البته هنوز lodash برای ما نصب نشده است بنابراین به ترمینال رفته و lodash را نصب کنید.

npm install lodash --save

حالا به فایل kiwi.js می رویم و همین کار را انجام می دهیم:

import Heading from './components/heading/heading.js';
import KiwiImage from './components/kiwi-image/kiwi-image.js';
import _ from 'lodash';

const heading = new Heading();
heading.render(_.upperFirst('kiwi'));
const kiwiImage = new KiwiImage();
kiwiImage.render();

حالا دستور npm run build را اجرا کنید. به نظر شما درون Dist چه چیزی خواهیم دید؟ اگر به همان پنجره ترمینال نگاه کنید متوجه می شوید که فایل های جاوا اسکریپت ما (چه kiwi و چه hello-world) هر کدام حدود 70 کیلوبایت شده اند که برای چهار خط کد ساده ما حجم بسیار زیادی است! مشکل اینجاست که webpack تمام کدهای lodash را نیز درون کدهای ما قرار داده است چرا که یک وابستگی محسوب می شود و هر بار که دستور npm run build را بزنیم تا فایل های جدیدی داشته باشیم، این کتابخانه درون کدهای ما خواهد بود. بدتر این که هر بار نام فایل های ما عوض می شود (به خاطر contenthash) که باعث از دست رفتن کش می شود. به زبان ساده تر هر بار که ما تغییری در کدهایمان ایجاد کنیم، کاربر باید حجم زیادی از کد را دانلود کند که اکثر آن نیز تکراری است.

خوشبختانه webpack می تواند با مکانیسم خاصی، وابستگی ها را درون یک bundle جداگانه قرار دهد تا با تغییر کدهای ما وابستگی ها تغییر نکنند و کاربران بتوانند از همان کش مربوط به وابستگی ها استفاده کنند. برای این کار به فایل webpack.production.config.js بروید و پایین تر از mode خصوصیت جدیدی به نام optimization ایجاد نمایید:

module.exports = {
    entry: {
        'hello-world': './src/hello-world.js',
        'kiwi': './src/kiwi.js'
    },
    output: {
        filename: '[name].[contenthash].js',
        path: path.resolve(__dirname, './dist'),
        publicPath: '/static/'
    },
    mode: 'production',
    optimization: {
        splitChunks: {
            chunks: 'all',
        }
    },
// بقیه کدها //

با اضافه کردن این خط کد دوباره npm run build را اجرا می کنم و به پوشه Dist می روم. هر کدام از فایل های جاوا اسکریپتی ما حدود 1 کیلوبایت حجم دارند و یک فایل سوم جاوا اسکریپتی نیز اضافه شده است که vendors~hello-world~kiwi.3a856s9375b92.js نام دارد (این نام برای شما فرق خواهد کرد) که همان کتابخانه lodash است.

سوال بعدی اینجاست که webpack از کجا می داند این فایل جاوا اسکریپت سوم را در چه صفحاتی وارد کند؟ این مسئله به عهده ما است و باید به طور خاص به webpack بگوییم که این فایل را در چه قسمت هایی لازم داریم. در پروژه ما هر دو صفحه ما به این فایل نیاز دارند (در هر دو از متد upperFirst استفاده کرده ایم) بنابراین در همان فایل پیکربندی می گوییم:

     plugins: [
        new MiniCssExtractPlugin({
            filename: '[name].[contenthash].css'
        }),
        new CleanWebpackPlugin('dist'),
        new HtmlWebpackPlugin({
            filename: 'hello-world.html',
            chunks: ['hello-world', 'vendors~hello-world~kiwi'],
            title: 'Hello world',
            description: 'Hello world',
            template: 'src/page-template.hbs'
        }),
        new HtmlWebpackPlugin({
            filename: 'kiwi.html',
            chunks: ['kiwi', 'vendors~hello-world~kiwi'],
            title: 'Kiwi',
            description: 'Kiwi',
            template: 'src/page-template.hbs'
        })
    ]

همانطور که می بینید من chunk ها را به روز رسانی کرده و حالا فایل سوم جاوا اسکریپتی خودم را نیز به آن ها اضافه کرده ام (نیازی نیست قسمت hash را به آن اضافه کنید). بار دیگر دستور npm run build را اجرا می کنیم و به مرورگر می رویم. حالا هر دو صفحه ما باید بدون مشکل اجرا شوند. من دو مسیر زیر را در مرورگر خودم باز کرده ام:

file:///E:/Development/webpack/26%20Webpack%204/00%20Articles/files/02/webpack4/dist/kiwi.html

file:///E:/Development/webpack/26%20Webpack%204/00%20Articles/files/02/webpack4/dist/hello-world.html

اما این مسیر ها برای شما تفاوت خواهد داشت چرا که احتمالا پوشه های شما در آدرسی جداگانه قرار دارد. تفاوتی ندارد که آدرس ها را به صورت دستی وارد کنید یا از سرور توسعه Webpack استفاده کنید. در هر حال اگر در قسمت dev tools مرورگر خود سربرگ network را باز کنید باید سه فایل مختلف جاوا اسکریپت را مشاهده کنید: فایل hello-world.js و kiwi.js و vendors که البته فقط دو تای آن ها در هر صفحه قابل مشاهده هستند.

سوال: آیا این روش فقط برای پروژه های MPA است؟

پاسخ: خیر. اگر پروژه شما SPA است هنوز هم می توانید از این تکنیک استفاده کنید. محوریت اصلی این تکنیک بر browser caching تکیه دارد و فایده اصلی آن هم همین می باشد. هدف ما این است که با هر بار ویرایش کدهای برنامه، کاربر را مجبور به دانلود دوباره وابستگی های پروژه نکنیم.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش Webpack توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.