البدء
يُعتبر Webpack خيارًا ممتازًا عندما يحتاج تطبيقك إلى مسار بناء (Build Pipeline) قابل للتخصيص: مثل تجميع وحدات JavaScript، ومعالجة الملفات (assets)، ودمج الـ loaders والـ plugins، وتشكيل المخرجات لبيئات مختلفة. بالنسبة لصفحة صغيرة جدًا تحتوي على ملف أو ملفين JavaScript فقط، قد لا تحتاج إلى bundler في البداية؛ ولكن في التطبيقات التي تحتوي على تبعيات مشتركة، وحزم npm، وملفات assets، وبناءات للإنتاج (production builds)، فإن webpack يمنحك تحكمًا واضحًا بكيفية تجميع كل شيء.
يُستخدم Webpack لتجميع وحدات JavaScript بكفاءة. بعد تثبيته، يمكنك التعامل معه إما من خلال واجهة سطر الأوامر CLI أو من خلال واجهة API. إذا كنت جديدًا على webpack، فننصحك بقراءة المفاهيم الأساسية وهذه المقارنة لتفهم لماذا قد تختاره بدلًا من الأدوات الأخرى الموجودة في المجتمع البرمجي.
البداية السريعة (مثال عملي بسيط)
إذا كنت تريد تشغيل مشروع webpack جاهز بسرعة، فإن أسهل طريقة هي إنشاء مشروع باستخدام create-webpack-app.
npx create-webpack-app webpack-demo
cd webpack-demoالإعداد الأساسي
لنقم أولًا بإنشاء مجلد للمشروع، ثم تهيئة npm، وتثبيت webpack محليًا، بالإضافة إلى تثبيت webpack-cli (الأداة المستخدمة لتشغيل webpack من سطر الأوامر):
# نفّذ الأوامر الخاصة بمدير الحزم الذي تستخدمه فقط.
mkdir webpack-demo
cd webpack-demo
# npm
npm init -y
npm install webpack webpack-cli --save-dev
# yarn
yarn init -y
yarn add webpack webpack-cli --dev
# pnpm
pnpm init
pnpm add webpack webpack-cli -Dخلال الأدلة سنستخدم كتل diff لتوضيح التغييرات التي نقوم بها على الملفات والمجلدات والكود. على سبيل المثال:
+ هذا سطر جديد يجب عليك إضافته إلى الكود
- وهذا سطر يجب حذفه من الكود
وهذا سطر لا يجب تعديله.الآن سننشئ بنية المجلدات والملفات التالية:
project
webpack-demo
├── package.json
├── package-lock.json
+ ├── index.html
+ └── src/
+ └── index.jssrc/index.js
function component() {
const element = document.createElement("div");
// Lodash, currently included via a script, is required for this line to work
element.innerHTML = _.join(["Hello", "webpack"], " ");
return element;
}
document.body.appendChild(component());index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Getting Started</title>
<script src="https://unpkg.com/lodash@4.17.21"></script>
</head>
<body>
<script src="./src/index.js"></script>
</body>
</html>نحتاج أيضًا إلى تعديل ملف package.json للتأكد من تعيين الحزمة كـ private، بالإضافة إلى إزالة خاصية main. الهدف من ذلك هو منع نشر الكود بالخطأ.
سنضيف أيضًا "type": "module" حتى يتعامل Node.js مع ملفات .js في المشروع على أنها ES Modules. هذا الإعداد يطبَّق على كامل المشروع، بما في ذلك ملفات إعداد webpack والسكريبتات المستقبلية الخاصة بـ Node.js. إذا كنت تفضل الإبقاء على سلوك CommonJS الافتراضي، يمكنك حذف "type": "module" واستخدام require(...) و module.exports بدلًا من import و export default.
package.json
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "",
- "main": "index.js",
+ "private": true,
+ "type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "MIT",
"devDependencies": {
"webpack": "^5.105.0",
"webpack-cli": "^7.0.0"
}
}في هذا المثال توجد تبعيات ضمنية بين وسوم <script>. ملف index.js يعتمد على وجود مكتبة lodash داخل الصفحة قبل تشغيله. هذا يُنشئ اعتمادًا ضمنيًا على متغير عام (_) مما يجعل ترتيب تنفيذ السكربتات مهمًا وصعب الصيانة.
هناك عدة مشاكل في إدارة مشاريع JavaScript بهذه الطريقة:
- ليس من الواضح مباشرة أن السكربت يعتمد على مكتبة خارجية.
- إذا كانت إحدى التبعيات مفقودة أو تم تحميلها بترتيب خاطئ، فلن يعمل التطبيق بشكل صحيح.
- إذا تم تحميل تبعية غير مستخدمة، سيضطر المتصفح إلى تنزيل كود غير ضروري.
يقوم Webpack بحل هذه المشاكل من خلال التصريح بالتبعيات بشكل واضح وتجميعها معًا. هذا يُزيل الاعتماد على المتغيرات العامة ويضمن تنفيذ السكربتات بالترتيب الصحيح.
إنشاء Bundle
سنقوم أولًا بتعديل بنية المشروع قليلًا، وذلك بفصل كود المصدر (./src) عن كود التوزيع (./dist).
- كود المصدر هو الكود الذي سنكتبه ونعدّله.
- كود التوزيع هو المخرجات النهائية المصغّرة والمحسّنة الناتجة عن عملية البناء والتي سيتم تحميلها في المتصفح.
قم بتعديل بنية المشروع كالتالي:
project
webpack-demo
├── package.json
├── package-lock.json
+ ├── /dist
+ │ └── index.html
- ├── index.html
└── /src
└── index.jsمجلد dist يحتوي على مخرجات البناء، لذلك عادةً لا يتم تعديل الملفات بداخله يدويًا في المشاريع الحقيقية. نحن ننقل index.html إليه مؤقتًا فقط حتى يتمكن المتصفح من تحميل الـ bundle الأول الذي سيتم إنشاؤه. لاحقًا، في دليل آخر، سنجعل webpack ينشئ ملف index.html تلقائيًا بدلًا من تعديله يدويًا.
لكي نقوم بتجميع تبعية lodash مع index.js، يجب علينا تثبيت المكتبة محليًا:
# نفّذ الأمر الخاص بمدير الحزم الذي تستخدمه فقط.
# npm
npm install lodash
# yarn
yarn add lodash
# pnpm
pnpm add lodashالآن لنقم باستيراد lodash داخل السكربت:
src/index.js
+import _ from 'lodash';
+
function component() {
const element = document.createElement('div');
- // Lodash, currently included via a script, is required for this line to work
+ // Lodash, now imported by this script
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}
document.body.appendChild(component());وبما أننا سنقوم الآن بتجميع السكربتات، يجب علينا تحديث ملف index.html. سنقوم بحذف وسم <script> الخاص بـ lodash لأننا نستوردها الآن باستخدام import، ثم سنعدّل الوسم الآخر ليحمّل الـ bundle بدلًا من ملف ./src مباشرة:
dist/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Getting Started</title>
- <script src="https://unpkg.com/lodash@4.17.21"></script>
</head>
<body>
- <script src="./src/index.js"></script>
+ <script src="main.js"></script>
</body>
</html>في هذا الإعداد، يقوم index.js بطلب lodash بشكل صريح وربطها بالمتغير _ بدون تلويث الـ global scope. من خلال التصريح بالتبعيات المطلوبة، يستطيع webpack بناء dependency graph ثم استخدامه لإنشاء bundle محسّن يتم تنفيذ السكربتات فيه بالترتيب الصحيح.
الآن لنقم بتشغيل npx webpack من داخل مجلد المشروع. إذا كان webpack مثبتًا محليًا، فسيقوم npx بتشغيل النسخة الموجودة داخل node_modules/.bin.
# نفّذ الأمر الخاص بمدير الحزم الذي تستخدمه فقط.
# npm
npx webpack
# yarn
yarn webpack
# pnpm
pnpm exec webpackسيأخذ webpack الملف src/index.js كنقطة دخول (entry point) ويقوم بإنشاء dist/main.js كمخرج (output).
افتح ملف index.html الموجود داخل dist باستخدام المتصفح، وإذا سار كل شيء بشكل صحيح فسترى النص التالي:
Hello webpackالوحدات (Modules)
تم توحيد أوامر import وexport ضمن معيار ES2015. وهي مدعومة حاليًا في أغلب المتصفحات، لكن بعض المتصفحات القديمة لا تتعرف على هذا الأسلوب الجديد. لا تقلق، webpack يدعمه بشكل افتراضي.
خلف الكواليس، يقوم webpack بتحليل dependency graph الخاص بالمشروع وتجميع الوحدات بالترتيب الصحيح. كما يدعم عدة أنظمة للوحدات بالإضافة إلى import و export.
لاحظ أن webpack لا يقوم بتحويل أي كود آخر غير أوامر import و export. إذا كنت تستخدم ميزات أخرى من ES2015، فتأكد من استخدام transpiler مثل Babel من خلال نظام الـ loaders.
استخدام ملف إعدادات
ابتداءً من الإصدار 4، لم يعد webpack يتطلب ملف إعدادات، لكن أغلب المشاريع تحتاج إلى إعدادات أكثر تعقيدًا، ولهذا يدعم webpack وجود ملف إعدادات.
ملفات إعداد webpack يمكن كتابتها باستخدام CommonJS أو ECMAScript Modules. الأمثلة التالية تستخدم صيغة ESM الحديثة.
project
webpack-demo
├── package.json
├── package-lock.json
+ ├── webpack.config.js
├── /dist
│ └── index.html
└── /src
└── index.jswebpack.config.js
import path from "node:path";
import { fileURLToPath } from "node:url";
// In Node.js versions prior to native support for import.meta.dirname,
// derive __dirname from import.meta.url.
// (Node 20.11+ supports import.meta.dirname and import.meta.filename.)
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default {
entry: "./src/index.js",
output: {
filename: "main.js",
path: path.resolve(__dirname, "dist"),
},
};الآن دعنا نعيد تشغيل البناء باستخدام ملف الإعدادات الجديد:
# npm
npx webpack --config webpack.config.js
# yarn
yarn webpack --config webpack.config.js
# pnpm
pnpm exec webpack --config webpack.config.jsيمنحك ملف الإعدادات مرونة أكبر بكثير مقارنة باستخدام CLI فقط، حيث يمكنك تحديد loaders و plugins وخيارات resolve وغير ذلك.
سكربتات NPM
بدلًا من تشغيل webpack يدويًا في كل مرة، يمكننا إنشاء اختصار داخل package.json باستخدام npm scripts:
package.json
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^5.105.0",
"webpack-cli": "^7.0.0"
},
"dependencies": {
"lodash": "^4.17.21"
}
}الآن يمكنك استخدام الأمر:
npm run buildبدلًا من npx webpack.
npm run build -- --colorالخاتمة
الآن بعد أن أصبح لديك إعداد بناء أساسي، يمكنك الانتقال إلى الدليل التالي Asset Management لتتعلم كيفية إدارة الصور والخطوط وبقية الملفات باستخدام webpack.
يجب أن تبدو بنية مشروعك الآن بالشكل التالي:
project
webpack-demo
├── package.json
├── package-lock.json
├── webpack.config.js
├── /dist
│ ├── main.js
│ └── index.html
├── /src
│ └── index.js
└── /node_modulesإذا كنت تريد معرفة المزيد عن تصميم webpack، يمكنك قراءة صفحات المفاهيم الأساسية والإعدادات، بالإضافة إلى قسم API الذي يشرح الواجهات المختلفة التي يوفرها webpack.



