آموزش تنظیم webpack 4 (وب پک ۴) در ساده ترین حالت (۱)

ساده‌ترین هم که نه :) ساده ترین فرم استفاده از وب پک نیازی به فایل کانفیگ نداره، پس ما هم فعلا باهاش کاری نداریم


قسمت اول: ماژول باندلر TL;DR

قصد این قسمت فقط معرفی و پیدا کردن حتی یک دلیل برای استفاده از وب پکه پس اگر قطعا قصد دارید از وب پک استفاده کنید و میدونید دارید چکار میکنید میتونید از این قسمت بگذرید


خوب سوال اول اینه که آیا استفاده از وب پک یک الزامه یا یک انتخاب؟ سوال لطفا یادتون باشه تا یک سوال دیگه مطرح کنیم و کم کم به جواب برسیم. وب پک چیست؟ وِب پَک یک ماژول باندلره... پس اولا اگر شما قصدی بر نوشتن یک برنامه ماژولار ندارید به وب پک هم نیازی نیست پس ادامه جواب بر مبنای این فرضیه ست که شما قصد دارید یک برنامه ماژولار بنویسید... وب پک یک ماژول باندلر برای جاوااسکریپته... آیا شما برنامه ماژولار خودتونُ با جاوا اسکریپت مینویسید؟ اگر جواب شما مثبته این سوال مطرح میشه که آیا وب پک تنها گزینه شماست؟

دو مدل Module Definition معروفی که برای جاوا اسکریپت ارایه شده‌اند و احتمالا نام آنها به گوشتان خورده باشد CommonJS که اختصارا CJS هم نامیده میشود و AMD (که یکی از مشتقات معروف آن RequireJS است) هستند، در واقع CJS یک مدل Synchronous (همگام) برای سمت سرور (NodeJS)‌ است و AMD که مخفف (Asynchronous module definition) است یک مدل Asynchronous برای سمت کلاینت (Browser) به شمار میرود اما در سال ۲۰۱۵ یک ماژول سیستم استاندارد به عنوان ES6 یا ES2015 معرفی شد که مفاهیمی رو برای نحوه ایمپورت و اکسپورت ماژول‌ها به صورت غیرهمگام یا Asynchronous ارایه کرد.
وظیفه ماژول باندلرها سرهم کردن ماژول‌هاست که در فایل‌های مختلف نوشته شده‌اند و احتمالا رفرنسی هم به یکدیگر دارند، چیزی که مشخصه ترتیب لود شدن ماژول‌ها توی فایل باندل مهمه چون ممکنه رفرنسی از ماژول A توی ماژول B وجود داشته باشه بنابر‌این مهمه که ماژول A قبل از ماژول B توی باندل قرار بگیرهپس مهمترین وظیفه ماژول باندلرها هم همینه که ماژول‌ها به ترتیب باندل شوند و در واقع باندلر یک یا چند فایل optimize شده از فایل‌های سورسی که به اون داده شده میسازه که در فاز پروداکشن مورد استفاده قرار میگیرند.
در حقیقت ماژول باندلینگ به دو شکل اتفاق میفته یکی در حین development که وقت runtime ماژول ها باندل می شوند و یکی هم برای فاز پروداکشن هست که این باندل‌ها اصطلاحا build میشوند و فایل بیلد شده که عموما minify و uglify هم شده برای استفاده کاربران توی پروژه قرار میگیره.

از معروف ترین باندلر های میشه به Webpack، Rollup و Google Closure Compiler اشاره کرد.

این مورد سوم یعنی Google Closure Compiler در واقع یک Code Analyzer و Code Optimizer هست که کار باندل کردن رو هم انجام میده، اگر هدف شما فقط آنالیز کردن کدتون و در نهایت کم کردن حجم اون برای افزایش سرعت اجراست میتونه انتخاب بسیار خوبی باشه. در واقع اکثر باندلرها فیچرها و نهایتا عملکرد مشابهی دارند و موردی که بیش از همه بین اونها متفاوت هست tree shaking نامیده میشه و متعلق به مدل‌های CJS و ES هست به این شکل که موقع باندل کردن چک میکنه کدوم ماژول‌ها یا قسمت‌هایی از اونها جایی استفاده نشده‌ند و حذف اونها از باندل نهایی آسیبی به عملکرد نهایی مورد نظر وارد نمیکنه و با حذف اونها حجم باندل را تقلیل میدهد، در این مورد Webpack بهترین عملکرد را بین باندلرهای دیگه داره.

قسمت دوم: توضیحات من

اگر قبلا با Webpack کار کرده باشید میدانید (یا اگر نکرده‌اید بدانید) که تنظیم وب پک گیج کننده‌ست با اینکه سایت اصلی آموزش خوب و کاملی ارایه میده اما بنا به دلایلی وب پک اسب رامی نیست که به همین راحتی‌ها به شما سواری بده. مخصوصا به عنوان کسی که تازه با وب پک آشنا شدید مطالعه سورس کانفیگ‌های دیگران بیشتر شما رو سردرگم میکنه و احتمالا نهایتا شما رو به مرض وب پک زدگی دچار کنه مرضی که من ماه‌ها دچارش بودم و اخیرا بخاطر یک پروژه که حتما باید از وب پک برای جمع کردنش استفاده میکردم خودم رو با دیدن چند ساعتی فیلم آموزشی و خوندن چند مقاله مدیومی درمان کردم و فکر میکنم آموزش‌های وب پک فاقد یک متن خیلی ساده و ابتدایی برای فهم اصول اولیه هستند بنابراین یک سناریو خیلی ساده تعریف میکنم و برای این سناریو وب پک رو تنظیم میکنیم.

قسمت سوم: سناریو

الف) در این سناریو ما با هیچ فریم ورکی سر و کار نداریم (البته توی ذهنم دارم که در آینده یک سناریو برای ReactJS بنویسم و در اون یک اپلیکیشن React بدون استفاده از دستور create-react-app بسازیم پس اگر شما طرفدار reactjs هستید من رو فالو کنید)
ب) در این سناریو ما کد جاوااسکریپت رو با مدل ES6 مینویسیم و میخوایم که وب پک کد‌های ما رو قبل از باندل کردن به ES5 اصطلاحا transpile کنه (اگر با اسطلاح ترنسپایل آشنا نیستید بهتره فرقش رو با کامپایل بگم که بهتر درک کنید: در فرایند کامپایل عموما کد شما توسط کامپایلر از یک زبان سطح بالا به یک زبان سطح پایین یا عموما زبان ماشین ترجمه میشه یعنی به احتمال زیاد کد ترجمه شده برای انسان قابل خواندن نیست اما در فرایند ترنسپایل عمدتا کد از نسخه ای از یک زبان سطح بالا به نسخه دیگری از همون زبان ترجمه میشه که نسخه ترجمه شده هم قابل خواندن برای انسان است (human readable) یعنی قاعدتا نسخه ترنسپایل شده هم باید به یک کامپایلر سپرده بشه) دلیل ترنسپایل کردن کد اینه که ES6 یک استاندارد جدیده که توسط همه browserها هنوز پشتیبانی نمیشه بنابراین وقتی ما کد رو از ES6 به ES5 ترنسپایل میکنیم عملا داریم کد نوشته شده مون رو که از قواعد ماژولار نوشتن بهره بردیم downgrade میکنیم به یک نسخه ساده‌تر که بروزرهای قدیمی تر هم پشتیبانی میکنند. برای ترنسپایل کردن وب پک کاری از دستش ساخته نیست و ما از یک transpiler به اسم Babel در وب پک استفاده میکنیم.
ج) بجای CSS میخوایم با SASS استایل‌هامون رو بنویسیم و توقع داریم Webpack اونها رو به CSS ساده تبدیل کنه برای این فرایند دیگه حتی از اصطلاح transpile هم استفاده نمیشه چون واقعا داریم چند تا تگ ساده رو به مدل دیگه تبدیل میکنیم به این فرایند میگیم transform یا همون تبدیل.
د) گفتم که باندلرها قرار نیست فقط برامون ماژول باندل کنند و فیچرهای دیگه ای هم دارند (که تا اینجا با ترنسپایل و ترنسفر و تری شیکینگ آشنا شدید) یکی از کارهای باحالی که وب پک انجام میده اینه که هربار که شما کد خودتون رو در فاز دولوپمنت باندل میکنید وب پک برای نام فایل‌های شما (یا ادامه اسم اصلی فایل) یک رشته کاراکتر معمولا عددی تصادفی md5 میسازه. احتمالا با این مشکل مواجه شدید که یک فایل کد یا مدیای شما اصطلاحا توسط browser یا سرور کش میشه و حتی با وجود تغییر محتوا شما هربار فایل قبلی رو میبینید و مجبورید در ساده ترین حالت کش بروزر رو پاک کنید و یا دستی اسم فایل رو تغییر بدید که در نتیجه بایستی تمام رفرنس‌هایی که به اون فایل دارید رو هم دستی تغییر بدید که مشکلتون حل بشه. وب پک این کارو مجانی براتون انجام میده و بصورت خودکار همه رفرنس‌ها به اون فایل رو هم update میکنه به این کار اصطلاحا cache busting میگن و "فرهنگستانِ ادبِ مَن" معادل فارسی "کاشه‌کُشی" براش انتخاب کرد که خیلی هم از خودم خوشم اومد.

قسمت چهارم: هدف

قراره که ما به وسیله وب پک تمام فایل‌‌های جاوااسکریپت، استایل‌ها، عکس‌ها و فونت‌هایی که داریم رو باندل کنیم و در‌نهایت بایک فایل جاوااسکریپت و یک فایل css باندل شده که minify (فشرده با مکانیزم‌های خاص) شده‌اند طرف باشیم که توی فایل index.html لود میشوند. در این پروژه از گیت هم استفاده میکنیم ولی هدف آموزش گیت نیست. هدف اینه که فایل‌های این پروژه به عنوان یک رفرنس برای شما بمونه که اگر نیاز داشتید بتونید کلون کنید و با کد خودتون مقایسه کنید.

خوب یک نفس راحت بکشید چون دیگه قراره کد بنویسیم و حرف زدن کافیه:

قسمت پنجم: let's do it

  • پیش زمینه:
    - من از visual studio code به عنوان ادیتور استفاده میکنم پیشنهادش هم میکنم و حتما یک آموزش برای کانفیگ کردنش هم در آینده نزدیک میگذارم
    - توقع میره که شما node‌ و پکیج منیجر اون به اسم npm رو نصب داشته باشید اگر ندارید از اینجا نصبش کنید و npm هم همراهش به صورت اتوماتیک نصب میشه
    - یک فولدر با نام دلخواه بسازید(من اسم فولدر پروژه‌مُ گذاشتم webpackproject) و فایل package.json رو بوسیله npm ایجاد کنید برای این کار توی فولدری که ساختید این دستورُ وارد کنید:
npm init -y

سویچ -y در انتهای دستور باعث میشه که npm مقادیر پیشفرض رو برای فایل package.json بگذاره و از شما سوال نپرسه ما بعدا خودمون فایل رو ادیت میکنیم.


حالا وب پک رو نصب کنید:

npm install --save-dev webpack webpack-cli

وب پک برای انجام کارش احتیاج به یک نقطه شروع داره یعنی شما بایستی یک فایل رو بعنوان نقطه شروع برای وب پک مشخص کنید تا بتونه ماژول‌ها رو بر اساس ترتیب فراخوانی باندل کنه معمولا فایل‌هایی که قراره توسط وب پک باندل بشوند رو توی یک پوشه به نام src ذخیره میکنیم و فایل‌هایی که وب پک باندل میکنه و میسازه رو توی یک پوشه به اسم dist (این پوشه از سورس کنترل شما باید exclude يا خارج بشه).
بنابر این ما چهار پوشه و یک فایل index.js توی پوشه‌ای به اسم src میسازیم مثل شکل زیر:

حالا توی فولدر اصلی که بهش میگیم root یا روت از این به بعد یک فایل کانفیگ برای وب پک بسازید به اسم webpack.config.js و این کد‌ها رو توش وارد کنید:

const path = require("path");
module.exports = {
    entry: './src/javascript/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    mode: 'development'
};

خط اول ما یک متغیر به اسم path تعریف کرده‌ و کتابخانه path رو توی اون فراخوانی کردیم وب پک با استفاده از path میتونه در ادامه مسیر‌های مورد نیاز رو پیدا یا اصطلاحا resolve کنه.

توی بلاک بعدی یعنی داخل براکت‌های module.exports تمام جادوی وب پک اتفاق خواهد افتاد و در نهایت ما هر خواسته ای از وب پک داریم باید توی اون براکت‌ها بنویسیم

در قسمت اول این بلاک ما اون فایل نقطه شروع یا entry point که قبلا توضیخ دادیم رو به وب پک معرفی میکنیم در اصل داریم یک آدرس relative‌ از همین جایی که هستیم (فایل webpack.config.js قرار داره) بهش میدیم به فایل index.js

در قسمت دوم آدرس و اسم فایل خروجی‌ای که توقع داریم باندل جاوااسکریپتمون ذخیره بشه بهش میدیم همونطور که مشخصه از کتابخانه path برای resolve کردن (پیدا کردن) آدرس فولدر dist استفاده کردیم.

توی آخرین خط هم ما فاز development رو برای وب پک مشخص کردیم. این مهمه که بدونیم فاز پیشفرض برای وب پک production هست و در این فاز وب پک موقع باندل کردن خیلی کارهای زیادی روی باندل انجام میده (مثلا minify) که توی مرحله دولوپمنت ما نیازی بهش نداریم چون زمان باندل کردن رو افزایش میده.

حالا فایل package.json رو باز کنید تا با هم ببینیم:

قاعدتا فایل شما با فایل من در بعضی قسمت‌ها متفاوته مشکلی نیست چون من گیت دارم توی پروژه‌م و بعضی از مقادیر رو پر کردم یا حتی احتمالا ورژن وب پک و webpack-cli شما ممکنه بیشتر باشه که اینها تاثیری در عملکرد پروژه نداره مگر اینکه زمان زیادی از تاریخ این آموزش گذشته و اتفاقای عجیب و غریب افتاده باشه که در اون حالت بهتره بگردید دنبال یک آموزش به روزتر.
خوب برای ما در حال حاضر قسمت scripts اهمیت داره در واقع در این قسمت ما میتونیم با اسکریپت‌های npm دستوراتی رو اجرا کنیم چه بهتر که این دستور برای باندل کردن فایل به وسیله وب پک باشه ;)

در اولین قدم دستور پیشفرضی که وجود داره با نام "test" و مقدار اون رو کامل پاک کنید و بجای یک دستور به شکل زیر برای بیلد کردن پروژه با وب پک بنویسید:

"scripts": {
    "build": "webpack --config webpack.config.js"
  },

حالا فرصت خوبیه که تنظیمات وب پک رو تست کنیم

یک دستور لاگ ساده توی فایل index.js بنویسید بعد دستور npmی که ساختید رو اجرا کنید یعنی در مرحله اول توی فایل index.js مثلا بنویسید و ذخیره کنید:

console.log("hello from webpack tutorial");

حالا توی روت پروژه این دستور رو اجرا کنید:

npm run build

اگر همه چیز درست پیش رفته باشه با یک همچین خروجی‌ای در ترمینال باید روبرو بشید:

این همه رنگ سبز نشون میده همه چی به خوبی پیش رفته و شما توی پوشه dist یک فایل bundle.js‌ درست و حسابی دارید که میتونید توی فایل index.html اونو فراخوانی کنید.(اگر از گیت استفاده میکنید این فولدر dist رو همین الان ignore‌ کنید)

فایل bundle.jsی که برای من ساخته شده ۱۰۰ خطه ما فقط یک خط نوشته بودیم که توی فایل من اون خط تو خط ۹۶ اجرا میشه:

در واقع بقیه خط‌ها مربوط به عملکرد وب پک هستند و در ادامه بیشتر از قبل با این عملکرد آشنا خواهیم شد.

برای دانلود سورس پروژه تا این مرحله به این آدرس مراجعه کنید و branch به نام 01 را از لیست branchها انتخاب کنید.

به زودی ادامه این آموزشُ بر اساس سناریو میگذارم.