آموزش جامع Webpack (بخش چهارم: ماژول ها در وب پک) – از صفر تا صد
در این بخش از سلسله مطالب آموزش جامع Webpack در مورد ماژول ها در وب پک صحبت میکنیم و توضیح میدهیم که اساساً در وب پک هر چیزی یک ماژول محسوب میشود. در بخشهای قبلی این سری مقالات یک اپلیکیشن کاملاً ساده با استفاده از Webpack و transpile کردن با ES2015+ ساختیم، اما اپلیکیشنهای واقعی بیش از این هستند و از CSS، تصاویر، فونتهای سفارشی و همه انواع فایلهای دیگر برخوردارند. برای مطالعه بخش قبلی این سری مقالات روی لینک زیر کلیک کنید:
نکته خوب این است که تا وقتی loader مناسبی برای این موارد داشته باشید، وب پک در کد شما با همه آنها به عنوان ماژولهای ES برخورد خواهد کرد.
ما کار خود را به این نحو آغاز کردیم که پیکربندی وب پک را تا حد امکان ساده حفظ کنیم و قصد داریم این رویه را نیز همچنان حفظ کنیم. در ادامه با شیوه راهاندازی loader-های بیشتر، ترکیب آنها و ارسال گزینههای مختلف به آنها آشنا میشویم.
ایمپورت کردن Meme-ها یا هر نوع تصویر دیگر
اینک نوبت به بارگذاری فایلها رسیده است. بنابراین یک دایرکتوری به نام assets در ریشه پروژه ایجاد میکنیم و هر تصویری که میخواهیم آنجا باشد را در آن ذخیره میکنیم. سپس میتوانیم از مثالهای زیر پیروی کنیم.
File loader
file-loader با تصاویر شما مانند هر فایل دیگری رفتار میکند و یک مسیر url در زمان ایمپورت کردن به آن اختصاص میدهد:
1import johnCena from "./assets/unexpected.jpg";
2
3document.body.innerHTML = '<div id="myMemes"></div>';
4document.getElementById("myMemes").innerHTML = `
5 <h1>And his name is...</h1>
6 <img src="${johnCena}" />
7`;
اگر این را بدون نصب اولیه file-loader اجرا کنید، وب پک خطایی به صورت زیر صادر میکند:
آن را نصب و سپس به فایل پیکربندی اضافه میکنیم:
yarn add file-loader –dev
قطعه کد زیر را به webpack.config.js در بخش module.rules اضافه میکنیم:
1module: {
2 rules: [
3 //...
4 {
5 test: /\.(gif|png|jpe?g|svg)$/i,
6 use: 'file-loader'
7 }
8 ]
9},
اگر بخواهیم regex فوق را ترجمه بکنیم، ما در این بخش میخواهیم هر فایلی که نام آن به یکی از پسوندهای gif ،.png، .jpg/.jpeg یا svg. ختم میشود و کوچکی و بزرگی حروف هم مهم نیست (فلگ i/ در انتها به همین منظور است) را انتخاب کنیم.
اکنون اگر آن را دوباره اجرا کنیم، وب پک اقدام به اجرای موفقیتآمیز build میکند.
Loader وبپک برای تصویر
استفاده همزمان از image-webpack-loader و file-loader بهینهسازی بسیار زیبایی برای فایلهای تصویر در اختیار ما قرار میدهد. اضافه کردن آن نیز آسان است:
yarn add image-webpack-loader –dev
و قاعده پس از file-loader را نیز اضافه میکنیم:
1{
2 test: /\.(gif|png|jpe?g|svg)$/i,
3 use: [
4 'file-loader',
5 {
6 loader: 'image-webpack-loader',
7 options: {
8 disable: true // Disables on development mode
9 }
10 }
11 ]
12}
برخی فشردهسازها از قبل به صورت پیشفرض فعال شدهاند:
- Mozjpeg – تصاویر JPEG را فشرده میسازد.
- Opting - تصاویر PNG را فشرده میسازد.
- Pngquant - تصاویر PNG را فشرده میسازد.
- Svgo - تصاویر SVG را فشرده میسازد.
- Gifsicle - تصاویر GIF را فشرده میسازد.
رسانه (صوتی و تصویری)
ما همانند کاری که با تصاویر کردیم، میتوانیم قاعدهای برای ویدئو و صوت که از سوی file-loader پردازش میشوند نیز تعیین کنیم.
کافی است قاعده زیر را به فایل webpack.config.js در بخش config.rules اضافه کنید:
1{
2 test: /\.(ogg|mp3|wav|mpe?g)$/i,
3 use: 'file-loader'
4}
چنان که میبینید از قبل یک قاعده برای file-loader وجود دارد، اما میتوانیم قواعد پیکربندی زیادی برای انواع مختلفی از فایلها اضافه کنیم. ما فایلهای رسانهای را تنها با استفاده از قاعدهای که با تصاویر انطباق دارد به هم اضافه کنیم، زیرا در بخش آخر آن را به webpack-image-loader اتصال دادهایم و احتمالاً در زمان خواندن یک فایل صوتی/ویدئویی مشکلساز میشود.
اکنون میتوانید فایلهای صوتی را همانند کاری که با تصاویر انجام دادید، ایمپورت کنید چون file-loader به روش مشابهی رفتار میکند و url منبع را به شما ارائه میدهد:
import andHisNameIs from "./assets/and-his-name-is.mp3";
در ادامه با این مورد نیز کار میکنیم و کد زیر را به انتهای فایل index.js میافزاییم:
1// ...
2const audio = new Audio(andHisNameIs);
3const img = document.querySelector("#myMemes img");
4
5img.addEventListener("click", event => audio.play());
شما میتوانید از هر فایل صوتی که میخواهید استفاده کنید، ما از این فایل (+) استفاده کردیم، اما توجه کنید که صدای این فایل کاملاً بلند است و نباید آن را در محیط کاری باز کنید!
افزودن استایلها به کمک Sass
در ادامه پشتیبانی Sass را نیز به اپلیکیشن خود اضافه میکنیم. همانند قبل باید loader-های مناسبی اضافه کرده و sass parser را نیز ادغام کنیم:
yarn add node-sass sass-loader css-loader style-loader –dev
اگر از دیدن این همه وابستگی شگفتزده شدهاید، باید بگوییم که هر وابستگی نقش ویژهای را به شرح زیر ایفا میکند:
- sass-loader + node-sass – فایلهای Sass را دریافت و خروجی CSS ارائه میکند.
- css-loader – آن را به ماژول جاوا اسکریپت تبدیل میکند.
- style-loader – ماژول CSS را دریافت کرده و آن را در صفحه درون تگ <style></style> قرار میدهد.
اگر این کد را به پیکربندی اضافه کنیم:
1module: {
2 rules: [
3 //...
4 {
5 test: /\.scss$/,
6 use: ["style-loader", "css-loader", "sass-loader"] // It's like a pipeline
7 }
8 ];
9}
میتوانیم کار را ادامه بدهیم و فایل style.scss را ایجاد و آن را در کد قرار دهیم:
1#myMemes {
2 text-align: center;
3 margin: auto auto;
4
5 h1 {
6 font-family: Arial, Helvetica, sans-serif;
7 color: #333;
8 }
9
10 img {
11 border-radius: 16px;
12 padding: 8px;
13 border: 1px solid #aaa;
14 box-shadow: 2px 2px 1px #eee;
15 cursor: pointer;
16 }
17}
اکنون یک ایمپورت در فایل index.js اضافه میکنیم:
1import johnCena from "./assets/unexpected.jpg";
2import "./style.scss";
3
4//....
استایلهای Production
هر ایمپورت که انجام میدهید، یک مدخل جدید <style></style> در هدر فایل ایجاد میشود. بدین ترتیب کار ممکن است به سرعت از کنترل خارج شود و از این رو شاید بهتر باشد همه فایلها را درهم ادغام و minify کنیم و یک فایل منفرد بهینه را عرضه نماییم. به این منظور یک راهحل به نام mini-css-extract-plugin وجود دارد.
برای نصب آن کافی است دستور زیر را اجرا کنید:
yarn add mini-css-extract-plugin –dev
آن را به build-های پروداکشن خود در فایل e webpack.config.js اضافه میکنیم و سپس فراخوانی require را نیز میافزاییم.
const MiniCssExtractPlugin = require(“mini-css-extract-plugin”);
سپس loader را به قاعده scss اضافه میکنیم، اما تنها در حالت production فعال میشود، در غیر این حالت، style-loader را حفظ میکنیم و از این فرصت استفاده کرده و پشتیبانی source-map را نیز اضافه میکنیم:
1{
2 test: /\.scss$/,
3 use: [
4 argv.mode === "production"
5 ? MiniCssExtractPlugin.loader
6 : "style-loader",
7 {
8 loader: "css-loader", options: {
9 sourceMap: true
10 }
11 },
12 {
13 loader: "sass-loader", options: {
14 sourceMap: true
15 }
16 }
17 ]
18}
در نهایت، همین کار را در مورد بخش plugins انجام میدهیم:
1plugins: [
2 // Any option given to Webpack client can be captured on the "argv"
3 argv.mode === "development" ? new HtmlWebpackPlugin() : null,
4 argv.mode === "production"
5 ? new MiniCssExtractPlugin({
6 filename: "[name].css",
7 chunkFilename: "[id].css"
8 })
9 : null
10].filter(
11 // To remove any possibility of "null" values inside the plugins array, we filter it
12 plugin => !!plugin
13);
با اجرای build میبینیم که بسته style در خروجی عرضه میشود:
تمیز نگه داشتن پیکربندی
چنان که مشاهده میکنید، پیکربندی هم اینک شروع به رشد کرده است. اما مزیت کار این است که این یک فایل Node.js است و میتوانیم آن را به تابعهایش افراز کنیم:
1const MiniCssExtractPlugin = require("mini-css-extract-plugin");
2
3module.exports = (env, argv) => [
4 {
5 test: /\.js$/,
6 use: "babel-loader"
7 },
8 {
9 test: /\.(gif|png|jpe?g|svg)$/i,
10 use: [
11 "file-loader",
12 {
13 loader: "image-webpack-loader",
14 options: {
15 disable: true // webpack@2.x and newer
16 }
17 }
18 ]
19 },
20 {
21 test: /\.(ogg|mp3|wav|mpe?g)$/i,
22 use: "file-loader"
23 },
24 {
25 test: /\.scss$/,
26 use: [
27 argv.mode === "production" ? MiniCssExtractPlugin.loader : "style-loader",
28 "css-loader",
29 "sass-loader"
30 ]
31 }
32];
و آن را در فایل webpack.config.js به صورت require تعریف کنیم:
1module: {
2 rules: require("./webpack/module.rules")(env, argv)
3},
اینک چنان که میبینید پیکربندی تمیزتر شده است و از آنجا که نام فایل از همان نام طرحواره پیکربندی پیروی میکند، میدانید که قواعد ماژول کجا قرار دارند.
اگر مطالبی که در بخش سوم (+) این سری مقالات آموختیم را به خاطر داشته باشید، میدانید که تمیز نگهداشتن پیکربندی امری بسیار مهم است.
اساساً loader-های وبپک و افزونهها در اغلب موارد از قالبی که در این بخش معرفی کردیم تبعیت میکنند. loader-های زیادی هم اینک وجود دارند و برخی از آنها از سوی تیم مرکزی توسعه Webpack طراحی شدهاند. برخی دیگر نیز از سوی جامعه اوپنسورس نوشته شدهاند.
در بخش بعدی این سری مقالات وارد مباحث عمیقتری میشویم. در قسمت بعدی راهاندازی ایمپورتهای دینامیک را در اپلیکیشن خود میآموزیم و همچنین راهبردهای افراز کد در Webpack را مورد بررسی قرار خواهیم داد. برای مطالعه بخش بعدی روی لینک زیر کلیک کنید:
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای JavaScript (جاوا اسکریپت)
- مجموعه آموزشهای برنامهنویسی
- ساخت اپلیکیشنهای مدرن با Webpack — به زبان ساده
- توسعه وب اپلیکیشن با جاوا اسکریپت و Webpack — راهنمای کاربردی
- آموزش جامع Webpack (بخش اول) — از صفر تا صد
==