Skip to main content Skip to docs navigation

الـ Bootstrap و (Webpack)

الدليل الرسمي حول كيفية تضمين وحزم الـ CSS والـ JavaScript الخاصة بـ Bootstrap في مشروعك باستخدام Webpack.

هل تريد الانتقال إلى النهاية؟ قم بتنزيل الكود المصدري والعرض التوضيحي الشغال لهذا الدليل من مستودع twbs/examples. يمكنك أيضاً فتح المثال في StackBlitz للتعديل المباشر.

ما هو Webpack؟

Webpack هو حازم وحدات JavaScript (module bundler) يقوم بمعالجة الوحدات (modules) والتبعيات الخاصة بها لإنشاء أصول ثابتة (static assets). وهو يسهل إدارة تطبيقات الويب المعقدة التي تحتوي على ملفات وتبعيات متعددة.

التثبيت (Setup)

نحن نقوم ببناء مشروع Webpack باستخدام Bootstrap من الصفر، لذا هناك بعض المتطلبات المسبقة والخطوات الأولية قبل أن نبدأ فعلياً. يتطلب هذا الدليل تثبيت Node.js وبعض المعرفة بالـ terminal.

  1. إنشاء مجلد للمشروع وإعداد npm. سنقوم بإنشاء مجلد my-project وتهيئة npm باستخدام الوسيط -y لتجنب طرح جميع الأسئلة التفاعلية علينا.

    mkdir my-project && cd my-project
    npm init -y
    
  2. تثبيت Webpack. نحتاج الآن إلى تثبيت تبعيات تطوير الـ Webpack: webpack لنواة الـ Webpack، و webpack-cli لنتمكن من تشغيل أوامر Webpack من الـ terminal، و webpack-dev-server لنتمكن من تشغيل خادم تطوير محلي. بالإضافة إلى ذلك، سنقوم بتثبيت html-webpack-plugin لنتمكن من تخزين ملف index.html في مجلد src بدلاً من مجلد dist الافتراضي. نستخدم --save-dev للإشارة إلى أن هذه التبعيات مخصصة للاستخدام في التطوير فقط وليس للإنتاج.

    npm i --save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin
    
  3. تثبيت الـ Bootstrap. يمكننا الآن تثبيت الـ Bootstrap. سنقوم أيضاً بتثبيت Popper لأن القوائم المنسدلة (dropdowns)، والنوافذ المنبثقة (popovers)، وتلميحات الأدوات (tooltips) تعتمد عليه في تحديد مواقعها. إذا كنت لا تخطط لاستخدام هذه المكونات، يمكنك تخطي تثبيت Popper هنا.

    npm i --save bootstrap @popperjs/core
    
  4. تثبيت تبعيات إضافية. بالإضافة إلى الـ Webpack والـ Bootstrap، نحتاج إلى بعض التبعيات الإضافية لاستيراد وحزم الـ CSS والـ JS الخاصة بـ Bootstrap بشكل صحيح باستخدام الـ Webpack. وتشمل هذه التبعيات الـ Sass، وبعض الـ loaders، و Autoprefixer.

    npm i --save-dev autoprefixer css-loader postcss-loader sass sass-loader style-loader
    

الآن بعد أن قمنا بتثبيت جميع التبعيات اللازمة، يمكننا البدء في إنشاء ملفات المشروع واستيراد الـ Bootstrap.

هيكل المشروع

لقد قمنا بالفعل بإنشاء مجلد my-project وتهيئة npm. الآن سنقوم أيضاً بإنشاء مجلدي src و dist لاستكمال هيكل المشروع. قم بتشغيل ما يلي من my-project ، أو قم بإنشاء هيكل المجلدات والملفات الموضح أدناه يدوياً.

mkdir {src,src/js,src/scss}
touch src/index.html src/js/main.js src/scss/styles.scss webpack.config.js

عندما تنتهي، يجب أن يبدو مشروعك الكامل بهذا الشكل:

my-project/
├── src/
│   ├── js/
│   │   └── main.js
│   ├── scss/
│   │   └── styles.scss
│   └── index.html
├── package-lock.json
├── package.json
└── webpack.config.js

في هذه المرحلة، كل شيء في مكانه الصحيح، ولكن الـ Webpack لن يعمل لأننا لم نقم بتعبئة ملف webpack.config.js الخاص بنا بعد.

تهيئة Webpack

بعد تثبيت التبعيات وتجهيز مجلد المشروع لنبدأ البرمجة، يمكننا الآن تهيئة الـ Webpack وتشغيل مشروعنا محلياً.

  1. افتح webpack.config.js في المحرر الخاص بك. بما أنه فارغ، سنحتاج إلى إضافة بعض الإعدادات الأساسية إليه حتى نتمكن من بدء تشغيل الخادم الخاص بنا. يخبر هذا الجزء من الإعدادات الـ Webpack بمكان البحث عن الـ JavaScript الخاص بمشروعنا، وأين يتم إخراج الكود المجمّع (dist)، وكيف يجب أن يتصرف خادم التطوير (السحب من مجلد dist مع التحديث التلقائي).

    'use strict'
    
    const path = require('path')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
      mode: 'development',
      entry: './src/js/main.js',
      output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist')
      },
      devServer: {
        static: path.resolve(__dirname, 'dist'),
        port: 8080,
        hot: true
      },
      plugins: [
        new HtmlWebpackPlugin({ template: './src/index.html' })
      ]
    }
    
  2. بعد ذلك نقوم بتعبئة ملف src/index.html. هذه هي صفحة HTML التي سيقوم الـ Webpack بتحميلها في المتصفح لاستخدام الـ CSS والـ JS المجمعة التي سنضيفها إليها في خطوات لاحقة. قبل أن نتمكن من القيام بذلك، يجب أن نعطيها شيئاً لتقوم بتصييره وتضمين الـ JS الخاص بـ output من الخطوة السابقة.

    <!doctype html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Bootstrap w/ Webpack</title>
      </head>
      <body>
        <div class="container py-4 px-3 mx-auto">
          <h1>Hello, Bootstrap and Webpack!</h1>
          <button class="btn btn-primary">Primary button</button>
        </div>
      </body>
    </html>
    

    نحن نقوم بتضمين القليل من تنسيقات الـ Bootstrap هنا باستخدام div class="container" و <button> حتى نتمكن من رؤية متى يتم تحميل الـ CSS الخاصة بـ Bootstrap بواسطة Webpack.

  3. الآن نحتاج إلى npm script لتشغيل الـ Webpack. افتح package.json وأضف الـ start script الموضح أدناه (يجب أن يكون لديك بالفعل الـ test script). سنستخدم هذا الـ script لبدء خادم تطوير الـ Webpack المحلي الخاص بنا. يمكنك أيضاً إضافة build script الموضح أدناه لبناء مشروعك.

    {
      // ...
      "scripts": {
        "start": "webpack serve",
        "build": "webpack build --mode=production",
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      // ...
    }
    
  4. وأخيراً، يمكننا بدء تشغيل الـ Webpack. من مجلد my-project في الـ terminal الخاص بك، قم بتشغيل الـ npm script الذي أضفته مؤخراً:

    npm start
    
    Webpack dev server running

في القسم التالي والأخير من هذا الدليل، سنقوم بإعداد الـ Webpack loaders واستيراد جميع ملفات الـ CSS والـ JavaScript الخاصة بـ Bootstrap.

استيراد الـ Bootstrap

يتطلب استيراد الـ Bootstrap في Webpack استخدام الـ loaders التي قمنا بتثبيتها في القسم الأول. لقد قمنا بتثبيتها باستخدام npm، ولكن الآن يجب تهيئة Webpack لاستخدامها.

  1. إعداد الـ loaders في webpack.config.js. ملف التهيئة الخاص بك الآن مكتمل ويجب أن يطابق المقتطف أدناه. الجزء الجديد الوحيد هنا هو قسم module.

    'use strict'
    
    const path = require('path')
    const autoprefixer = require('autoprefixer')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    
    module.exports = {
      mode: 'development',
      entry: './src/js/main.js',
      output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist')
      },
      devServer: {
        static: path.resolve(__dirname, 'dist'),
        port: 8080,
        hot: true
      },
      plugins: [
        new HtmlWebpackPlugin({ template: './src/index.html' })
      ],
      module: {
        rules: [
          {
            test: /\.(scss)$/,
            use: [
              {
                // Adds CSS to the DOM by injecting a `<style>` tag
                loader: 'style-loader'
              },
              {
                // Interprets `@import` and `url()` like `import/require()` and will resolve them
                loader: 'css-loader'
              },
              {
                // Loader for webpack to process CSS with PostCSS
                loader: 'postcss-loader',
                options: {
                  postcssOptions: {
                    plugins: [
                      autoprefixer
                    ]
                  }
                }
              },
              {
                // Loads a SASS/SCSS file and compiles it to CSS
                loader: 'sass-loader',
                options: {
                  sassOptions: {
                    // Optional: Silence Sass deprecation warnings. See note below.
                    silenceDeprecations: [
                      'mixed-decls',
                      'color-functions',
                      'global-builtin',
                      'import'
                    ]
                  }
                }
              }
            ]
          }
        ]
      }
    }
    

    إليك ملخص لسبب حاجتنا إلى جميع هذه الـ loaders. يقوم style-loader بحقن الـ CSS في عنصر <style> داخل الـ <head> لصفحة HTML، ويساعد css-loader في استخدام @import و url() و postcss-loader مطلوب لـ Autoprefixer، و sass-loader يسمح لنا باستخدام الـ Sass.

    ملاحظة: تظهر تحذيرات استبعاد (deprecation) الـ Sass عند تجميع ملفات Sass المصدرية باستخدام أحدث إصدارات Dart Sass. هذا لا يمنع التجميع أو استخدام الـ Bootstrap. نحن نعمل على حل طويل الأمد، ولكن في هذه الأثناء يمكن تجاهل إشعارات الاستبعاد هذه.

  2. الآن، لنقم باستيراد الـ CSS الخاصة بـ Bootstrap. أضف ما يلي إلى src/scss/styles.scss لاستيراد جميع الـ Sass المصدرية الخاصة بـ Bootstrap.

    // Import all of Bootstrap’s CSS
    @import "bootstrap/scss/bootstrap";
    

    يمكنك أيضاً استيراد أوراق الأنماط (stylesheets) الخاصة بنا بشكل فردي إذا كنت ترغب في ذلك. اقرأ مستندات استيراد الـ Sass لمزيد من التفاصيل.

  3. بعد ذلك نقوم بتحميل الـ CSS واستيراد الـ JavaScript الخاصة بـ Bootstrap. أضف ما يلي إلى src/js/main.js لتحميل الـ CSS واستيراد جميع الـ JS الخاصة بـ Bootstrap. سيتم استيراد Popper تلقائياً من خلال الـ Bootstrap.

    // Import our custom CSS
    import '../scss/styles.scss'
    
    // Import all of Bootstrap’s JS
    import * as bootstrap from 'bootstrap'
    

    يمكنك أيضاً استيراد الإضافات (plugins) الخاصة بـ JavaScript بشكل فردي حسب الحاجة لتقليل أحجام الحزمة (bundle):

    import Alert from 'bootstrap/js/dist/alert'
    
    // or, specify which plugins you need:
    import { Tooltip, Toast, Popover } from 'bootstrap'
    

    اقرأ مستندات الـ JavaScript الخاصة بنا لمزيد من المعلومات حول كيفية استخدام إضافات (plugins) الـ Bootstrap.

  4. لقد انتهيت! 🎉 مع تحميل الـ Sass والـ JS المصدرية الخاصة بـ Bootstrap بالكامل، يجب أن يبدو خادم التطوير المحلي الخاص بك الآن بهذا الشكل:

    Webpack dev server running with Bootstrap

    الآن يمكنك البدء في إضافة أي مكونات Bootstrap التي تريد استخدامها. تأكد من الاطلاع على مشروع مثال Webpack الكامل لمعرفة كيفية تضمين Sass مخصصة إضافية وتحسين عملية البناء الخاصة بك عن طريق استيراد الأجزاء التي تحتاجها فقط من الـ CSS والـ JS الخاصة بـ Bootstrap.

تحسينات الإنتاج

اعتماداً على إعداداتك، قد ترغب في تنفيذ بعض التحسينات الإضافية للأمان والسرعة المفيدة لتشغيل المشروع في بيئة الإنتاج. لاحظ أن هذه التحسينات غير مطبقة في مشروع مثال Webpack والأمر متروك لك لتنفيذها.

استخراج الـ CSS

يقوم الـ style-loader الذي قمنا بتكوينه أعلاه بإصدار الـ CSS في الحزمة بشكل مريح بحيث لا يكون تحميل ملف CSS يدوياً في dist/index.html ضرورياً. ومع ذلك، قد لا يعمل هذا النهج مع سياسة أمان محتوى (Content Security Policy) صارمة، وقد يصبح عنق زجاجة في تطبيقك بسبب حجم الحزمة الكبير.

لفصل الـ CSS بحيث يمكننا تحميله مباشرة من dist/index.html ، استخدم إضافة الـ mini-css-extract-loader الخاصة بـ Webpack.

أولاً، قم بتثبيت الإضافة:

npm install --save-dev mini-css-extract-plugin

ثم قم بإنشاء واستخدام الإضافة في تهيئة الـ Webpack:

--- a/webpack.config.js
+++ b/webpack.config.js
@@ -3,6 +3,7 @@
 const path = require('path')
 const autoprefixer = require('autoprefixer')
 const HtmlWebpackPlugin = require('html-webpack-plugin')
+const miniCssExtractPlugin = require('mini-css-extract-plugin')

 module.exports = {
   mode: 'development',
@@ -17,7 +18,8 @@ module.exports = {
     hot: true
   },
   plugins: [
-    new HtmlWebpackPlugin({ template: './src/index.html' })
+    new HtmlWebpackPlugin({ template: './src/index.html' }),
+    new miniCssExtractPlugin()
   ],
   module: {
     rules: [
@@ -25,8 +27,8 @@ module.exports = {
         test: /\.(scss)$/,
         use: [
           {
-            // Adds CSS to the DOM by injecting a `<style>` tag
-            loader: 'style-loader'
+            // Extracts CSS for each JS file that includes CSS
+            loader: miniCssExtractPlugin.loader
           },
           {

بعد تشغيل npm run build مرة أخرى، سيكون هناك ملف جديد dist/main.css ، والذي سيحتوي على جميع الـ CSS التي تم استيرادها بواسطة src/js/main.js. إذا قمت بعرض dist/index.html في متصفحك الآن، فستكون الأنماط مفقودة، لأنها موجودة الآن في dist/main.css. يمكنك تضمين الـ CSS الناتجة في dist/index.html على النحو التالي:

--- a/dist/index.html
+++ b/dist/index.html
@@ -3,6 +3,7 @@
   <head>
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
+    <link rel="stylesheet" href="./main.css">
     <title>Bootstrap w/ Webpack</title>
   </head>
   <body>

استخراج ملفات الـ (SVG)

تتضمن الـ CSS الخاصة بـ Bootstrap مراجع متعددة لملفات الـ (SVG) عبر الـ data: URIs المضمنة. إذا قمت بتحديد سياسة أمان محتوى (Content Security Policy) لمشروعك تمنع الـ data: URIs للصور، فلن يتم تحميل ملفات الـ (SVG) هذه. يمكنك تجاوز هذه المشكلة عن طريق استخراج ملفات الـ (SVG) المضمنة باستخدام ميزة asset modules في الـ Webpack.

قم بتهيئة الـ Webpack لاستخراج ملفات الـ (SVG) المضمنة على النحو التالي:

--- a/webpack.config.js
+++ b/webpack.config.js
@@ -23,6 +23,14 @@ module.exports = {
   },
   module: {
     rules: [
+      {
+        mimetype: 'image/svg+xml',
+        scheme: 'data',
+        type: 'asset/resource',
+        generator: {
+          filename: 'icons/[hash].svg'
+        }
+      },
       {
         test: /\.(scss)$/,
         use: [

بعد تشغيل npm run build مرة أخرى، ستجد ملفات الـ (SVG) مستخرجة في dist/icons ومشار إليها بشكل صحيح من الـ CSS.


هل لاحظت شيئاً خاطئاً أو قديماً هنا؟ يرجى فتح مشكلة على GitHub. هل تحتاج إلى مساعدة في استكشاف الأخطاء وإصلاحها؟ ابحث أو ابدأ نقاشاً على GitHub.