درس سوم: یکپارچه‌سازی webpack و پروژه و Loaderها (2)

Webpack Integration with Project and Loaders - ۲

22 شهریور 1399
درسنامه درس 3 از سری آموزش Webpack
02-Webpack-4-The-Complete-Tutorial-For-Beginners-lesson3

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

import Kiwi from './kiwi.jpg';

function addImage() {
    const img = document.createElement('img');
    img.alt = 'Kiwi';
    img.width = '458';
    img.src = Kiwi;

    const body = document.querySelector('body');
    body.appendChild(img);
}

همانطور که به شما گفتم Webpack نمی داند چطور فایل kiwi.jpg را وارد کند، بنابراین باید در فایل webpack.config.js به آن آموزش بدهیم:

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, './dist')
    },
    mode: 'none',
    module = {
        rules: []
    }
}

برای کار با فایل های اینچنینی باید خصوصیتی به نام module را تعریف کنیم که خودش یک شیء جاوا اسکریپتی است و خصوصیتی به نام rules دارد. rules آرایه ای از قوانین است که نحوه کار با انواع ماژول ها را مشخص می کند. هر کدام از این قوانین خودش باید یک شیء جاوا اسکریپتی باشد (اطلاعات بیشتر به همراه مثال در Documentation رسمی Webpack) که حداقل دو خصوصیت test و use را دارد:

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, './dist')
    },
    mode: 'none',
    module = {
        rules: [
            {
                test: /\.(png|jpg)$/,
                use: [
                    'file-loader'
                ]
            }
        ]
    }
}

همانطور که گفتم هر rule باید یک شیء باشد که حداقل test و use را داشته باشد. برای test باید یک regular expression (عبارات با قاعده) بنویسیم تا Webpack با استفاده از آن، فایل های مورد نظر ما را پیدا کند. مثلا عبارتی که بالاتر نوشته ام یعنی تمام فایل هایی که نامشان با png. یا jpg. تمام بشود. اگر با regular expression ها آشنایی ندارید، بهتر است در این مورد شروع به مطالعه کنید. در قسمت بعد که use است باید مشخص کنیم اگر فایل های مشخص شده در test پیدا شدند، با آن ها چه کار باید کرد. من اینجا گفته ام که از file-loader استفاده شود که یکی از loader های ارائه شده برای Webpack است (البته هنوز آن را نصب نکرده ایم). من برای اینکه یک مثال دیگر بزنم، فایل های XML را نیز به عنوان یک rule دیگر اضافه می کنم:

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, './dist')
    },
    mode: 'none',
    module = {
        rules: [
            {
                test: /\.(png|jpg)$/,
                use: [
                    'file-loader'
                ]
            },
            {
                test: /\.(xml)$/,
                use: [
                    'xml=loader'
                ]
            }
        ]
    }
}

در واقع با این کار Webpack به کدهای ما نگاه می کند و می گوید من باید فایلی به نام kiwi.jpg را import کرده و سپس درون DOM قرار بدهم. آیا من می دانم با فایل های jpg چطور رفتار کنم؟ اگر برایش تعریف کرده باشید (مانند کد بالا) یا فایل ما جزو فایل هایی باشد که مستقیما توسط Webpack پشتیبانی می شوند (مثل فایل های جاوا اسکریپت) کارش را طبق دستور Loader مربوطه انجام می دهد. در غیر این صورت به ما خطا خواهد داد.

در ضمن در حالت پیش فرض نام فایل های ما (مانند kiwi.jpg) به نام دیگری تغییر می کند که طبق فرمول زیر ایجاد می شود:

نسخه هش MD5 از محتویات فایل + پسوند اصلی فایل

شما می توانید مانند من rule مربوط به فایل های XML را حذف کرده (من فقط برای مثال آن را آوردم) و file-loader را نصب کنید:

npm install file-loader --save-dev

با اجرای دستور بالا file-loader برایمان نصب می شود. حالا webpack را اجرا کنید:

npm run build

اگر حالا به مرورگر برویم، می بینیم که تصویر کیوی ما موجود نیست. به نظر شما مشکل از کجاست؟ با مراجعه به dev tools مرورگر می بینیم که تگ img در صفحه موجود است اما خصوصیت src آن فقط نام فایل را گرفته (همان نام هش شده) و مسیر فایل را مشخص نکرده است. چرا؟ به دلیل اینکه پس از اجرای webpack تصویر ما در پوشه output (همان پوشه dist برای این پروژه) با نام جدید کپی خواهد شد. در حال حاضر تگ img من در مرورگر به شکل زیر است:

<img alt="Kiwi" width="458" src="c7df9e678830e101e0e530f5405ab8c5.jpg">

در حالی که src باید پوشه dist را نیز مشخص کند. به نظر شما راه حل چیست؟ راه حل استفاده از publicPath است:

const path = require('path');

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, './dist'),
        publicPath: 'dist/'
    },
// بقیه کدها //

با این کار می گوییم تصویر و کدهای ما درون پوشه dist است. حواستان باشد که حتما علامت اسلش انتهای publicPath را ذکر کنید. حالا اگر به مرورگر بروید، تصویر ما بدون مشکل قابل مشاهده است.

نکته: اگر بخواهید این پروژه را روی سرور اجرا کنید باید به publicPath آدرس سایت خود را بدهید. مثلا:

        publicPath: 'https://myWebsite.com/'

قبل از تمام کردن این جلسه دوست دارم یک نکته در رابطه با سئو برایتان توضیح بدهم. به نظر شما کدام یک از فایل های زیر برای سئو بهتر است؟

  1. e522a233d6cdf53aeaea3fb892541.png
  2. brief-description-of-the-image-contents.png

اگر کوچکترین زمینه کاری در دنیای وب داشته باشید می دانید که فایل دوم برای سئوی سایت ما بسیار بهتر است. webpack به صورت اتوماتیک نام فایل های ما را بر اساس محتویاتشان هش (hash) می کند. این کار برای استفاده از کش مرورگر عالی است چرا که اگر محتویات فایل هم تغییر کند، نام فایل یا همان هش هم تغییر کرده که باعث عدم استفاده از نسخه کش شده در مرورگر می شود (تا تغییرات جدید را در مرورگر ببینیم) اما همانطور که گفتم از نظر سئو اصلا خوب نیست.

اگر به صفحه رسمی file-loader در وب سایت webpack مراجعه کنید، توضیحاتی را در مورد این مسئله پیدا می کنید. اگر می خواهید کمی نام فایل ها را بهتر کنید، باید از گزینه options برای این rule استفاده کنید. مثال:

module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif)$/i,
        loader: 'file-loader',
        options: {
          name: '[path][name].[ext]',
        },
      },
    ],
  },
};

یعنی آدرس فایل کپی کن (مثلا اینجا یعنی درون dist یک پوشه به نام src ایجاد کن و عکس را درونش قرار بده) و نام فایل را دست نخورده باقی بگذار و در نهایت extention (پسوند فایل مانند jpg) را برایش قرار بده. با این کار نام فایل ها بهم نمی ریزد. همچنین اگر می خواهید از مزیت های هش دار بودن نام فایل استفاده کنید، می توانید یک هش ساده به انتهای نام آن اضافه کنید. مثلا فرض کنید فایلی به نام file.png داشته باشیم:

    module: {
        rules: [
            {
                test: /\.(png|jpg)$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: '[name][contenthash:5].[ext]'
                        }
                    }
                ]
            }
        ]
    }

با این کار نام فایل ما به همراه یک هش 5 رقمی خواهد بود. مثلا برای من نام زیر انتخاب شده است:

kiwic7df9.jpg

اطلاعات بیشتر را در وب سایت رسمی webpack پیدا خواهید کرد.

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

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

amin
09 بهمن 1399
این دوره خیلی عالیه تا جایی که ممکنه بی زحمت پیش برید تشکر از اقای زوارمی به خاطر مطالب بسیار خوبشون

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

octave
31 شهریور 1399
سلام خسته نباشید واقعا دوره ی خوبی هست، اگر امکان داره بیشتر در مورد وب پک اموزش بزارید در ضمن در کدی که قرار دادید کمی مشکل تایپی وجود داره، module = { rules: [] } بجای علامت مساوی در ماژول، باید دو نقطه بزاریم.

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