إدارة الملفات (Assets)
إذا كنت تتابع الأدلة من البداية، فمن المفترض أن لديك الآن مشروعًا صغيرًا يعرض النص "Hello webpack". والآن دعنا نحاول إضافة بعض الملفات الأخرى مثل الصور لنرى كيف يمكن التعامل معها.
قبل webpack، كان مطورو الواجهة الأمامية يستخدمون أدوات مثل grunt و gulp لمعالجة هذه الملفات ونقلها من مجلد /src إلى مجلدات مثل /dist أو /build. وكانت الفكرة نفسها تُستخدم مع وحدات JavaScript، لكن أدوات مثل webpack تقوم بتجميع جميع التبعيات بشكل ديناميكي (مما يُنشئ ما يُعرف باسم dependency graph). وهذا رائع لأن كل وحدة تقوم الآن بالتصريح عن تبعياتها بشكل واضح، كما سنتجنب تجميع الوحدات غير المستخدمة.
واحدة من أروع ميزات webpack هي أنه يمكنك أيضًا تضمين أي نوع آخر من الملفات بجانب JavaScript، طالما يوجد loader مناسب أو دعم مدمج من خلال Asset Modules. هذا يعني أن نفس الفوائد المذكورة سابقًا لـ JavaScript (مثل التبعيات الواضحة) يمكن تطبيقها على كل شيء يُستخدم لبناء موقع أو تطبيق ويب. لنبدأ مع CSS لأنك غالبًا معتاد بالفعل على هذا النوع من الإعداد.
الإعداد
لنقم بإجراء تعديل بسيط على المشروع قبل أن نبدأ:
dist/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
- <title>Getting Started</title>
+ <title>إدارة الملفات</title>
</head>
<body>
- <script src="main.js"></script>
+ <script src="bundle.js"></script>
</body>
</html>webpack.config.js
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
entry: './src/index.js',
output: {
- filename: 'main.js',
+ filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};تحميل ملفات CSS
لكي تتمكن من import ملف CSS من داخل وحدة JavaScript، تحتاج إلى تثبيت وإضافة style-loader و css-loader إلى إعدادات module:
npm install --save-dev style-loader css-loaderwebpack.config.js
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
+ module: {
+ rules: [
+ {
+ test: /\.css$/i,
+ use: ['style-loader', 'css-loader'],
+ },
+ ],
+ },
};يمكن ربط الـ loaders معًا في سلسلة. كل loader يقوم بتطبيق تحويلات على الملف الذي تتم معالجته. ويتم تنفيذ السلسلة بالعكس (من اليمين إلى اليسار).
على سبيل المثال:
export default {
module: {
rules: [
{
test: /\.scss$/i,
use: ["postcss-loader", "sass-loader"],
},
],
},
};بالرغم من أن postcss-loader يظهر قبل sass-loader داخل المصفوفة use، إلا أن webpack يقوم أولًا بتشغيل sass-loader (لتحويل Sass إلى CSS)، ثم يمرر النتيجة إلى postcss-loader.
إذا لم يتم الحفاظ على هذا الترتيب، فقد يقوم webpack بإظهار أخطاء.
project
webpack-demo
├── package.json
├── package-lock.json
├── webpack.config.js
├── /dist
│ ├── bundle.js
│ └── index.html
├── /src
+ │ ├── style.css
│ └── index.js
└── /node_modulessrc/style.css
.hello {
color: red;
}src/index.js
import _ from 'lodash';
+import './style.css';
function component() {
const element = document.createElement('div');
// Lodash, now imported by this script
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
+ element.classList.add('hello');
return element;
}
document.body.appendChild(component());الآن قم بتشغيل أمر البناء:
npm run buildافتح ملف dist/index.html في المتصفح مجددًا، وستلاحظ أن النص Hello webpack أصبح باللون الأحمر.
إذا أردت رؤية ما فعله webpack، قم بفحص الصفحة باستخدام أدوات المطور (Developer Tools) وليس "عرض مصدر الصفحة"، لأن وسم <style> يتم إنشاؤه ديناميكيًا بواسطة JavaScript.
لاحظ أنه يمكنك — وفي أغلب الحالات يجب عليك — تصغير ملفات CSS لتحسين سرعة التحميل في بيئة الإنتاج. كما توجد loaders لمعظم تقنيات CSS مثل postcss و sass و less.
تحميل الصور
الآن نحن نستورد CSS، لكن ماذا عن الصور مثل الخلفيات والأيقونات؟
ابتداءً من webpack 5، يمكننا استخدام Asset Modules المدمجة للتعامل مع الصور بسهولة:
webpack.config.js
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
+ {
+ test: /\.(png|svg|jpg|jpeg|gif)$/i,
+ type: 'asset/resource',
+ },
],
},
};الآن، عندما تقوم بكتابة:
import MyImage from "./my-image.png";سيقوم webpack بمعالجة الصورة وإضافتها إلى مجلد output، كما أن المتغير MyImage سيحتوي على الرابط النهائي للصورة بعد المعالجة.
عند استخدام css-loader، فإن url('./my-image.png') داخل CSS سيتم التعامل معه بالطريقة نفسها.
لنقم بإضافة صورة إلى المشروع:
project
webpack-demo
├── package.json
├── package-lock.json
├── webpack.config.js
├── /dist
│ ├── bundle.js
│ └── index.html
├── /src
+ │ ├── icon.png
│ ├── style.css
│ └── index.js
└── /node_modulessrc/index.js
import _ from 'lodash';
import './style.css';
+import Icon from './icon.png';
function component() {
const element = document.createElement('div');
// Lodash, now imported by this script
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
element.classList.add('hello');
+ // إضافة الصورة داخل العنصر الحالي
+ const myIcon = new Image();
+ myIcon.src = Icon;
+
+ element.appendChild(myIcon);
+
return element;
}
document.body.appendChild(component());src/style.css
.hello {
color: red;
+ background: url('./icon.png');
}قم بإعادة البناء وافتح الملف مجددًا:
npm run buildإذا سار كل شيء بشكل صحيح، فسترى الأيقونة كخلفية متكررة، بالإضافة إلى عنصر img بجانب النص Hello webpack.
إذا قمت بفحص العنصر، ستلاحظ أن اسم الملف الحقيقي أصبح شيئًا مثل:
29822eaa871e8eadeaa4.pngوهذا يعني أن webpack قام بمعالجة الملف بنجاح.
تحميل الخطوط
يمكن استخدام Asset Modules أيضًا للتعامل مع الخطوط (Fonts). لنقم بتحديث webpack.config.js:
webpack.config.js
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
+ {
+ test: /\.(woff|woff2|eot|ttf|otf)$/i,
+ type: 'asset/resource',
+ },
],
},
};أضف بعض ملفات الخطوط إلى المشروع:
+ │ ├── my-font.woff
+ │ ├── my-font.woff2يمكنك الآن استخدام @font-face داخل CSS:
src/style.css
+@font-face {
+ font-family: 'MyFont';
+ src: url('./my-font.woff2') format('woff2'),
+ url('./my-font.woff') format('woff');
+ font-weight: 600;
+ font-style: normal;
+}
+
.hello {
color: red;
+ font-family: 'MyFont';
background: url('./icon.png');
}قم بإعادة البناء وتحقق مما إذا تغير الخط.
تحميل البيانات
نوع آخر مفيد من الملفات هو البيانات مثل JSON و CSV و TSV و XML.
دعم JSON مدمج بالفعل داخل webpack، لذلك:
import Data from "./data.json";سيعمل مباشرة.
أما CSV و TSV و XML فتحتاج إلى loaders إضافية:
npm install --save-dev csv-loader xml-loaderثم أضفها إلى إعدادات webpack:
+ {
+ test: /\.(csv|tsv)$/i,
+ use: ['csv-loader'],
+ },
+ {
+ test: /\.xml$/i,
+ use: ['xml-loader'],
+ },بعدها يمكنك استيراد البيانات مثل أي ملف آخر:
import Notes from "./data.csv";
import Data from "./data.xml";وستحصل على بيانات JSON جاهزة للاستخدام.
تخصيص محلل JSON
يمكنك أيضًا استيراد ملفات toml و yaml و json5 باستخدام parser مخصص بدلًا من webpack loader.
قم أولًا بتثبيت الحزم:
npm install toml yamljs json5 --save-devثم أضف parsers مخصصة داخل webpack.config.js.
بعدها يمكنك الاستيراد بهذه الطريقة:
import json from "./data.json5";
import toml from "./data.toml";
import yaml from "./data.yaml";وسيتم تحويل البيانات إلى كائنات JavaScript تلقائيًا.
الملفات العامة (Global Assets)
أفضل جزء في هذا النظام هو أنه يسمح لك بتنظيم الملفات مع الكود المرتبط بها بدلًا من وضع كل شيء داخل مجلد /assets عام.
مثلًا:
- ├── /assets
+ └── /components
+ └── /my-component
+ ├── index.jsx
+ ├── index.css
+ ├── icon.svg
+ └── img.pngهذا يجعل الكود أكثر قابلية للنقل وإعادة الاستخدام.
إذا أردت نقل /my-component إلى مشروع آخر، يكفي نسخ المجلد طالما أن التبعيات الخارجية والـ loaders المطلوبة موجودة.
ومع ذلك، إذا كنت تفضل استخدام مجلد assets مركزي، فلا يزال ذلك ممكنًا، ويمكنك استخدام aliasing لتسهيل عمليات import.
إنهاء الدليل
في الأدلة القادمة لن نستخدم جميع الملفات التي أضفناها هنا، لذلك سنقوم ببعض التنظيف استعدادًا للدليل التالي Output Management.
قم بحذف الملفات والتعديلات التي أضفناها سابقًا، بالإضافة إلى إزالة التبعيات:
npm uninstall css-loader csv-loader json5 style-loader toml xml-loader yamljsالدليل التالي
لننتقل الآن إلى دليل Output Management
قراءة إضافية
- Loading Fonts على SurviveJS



