الإنتاج

في هذا الدليل، سنتعمق في بعض أفضل الممارسات والأدوات المساعدة لبناء موقع أو تطبيق للإنتاج.

الإعداد

تختلف أهداف بناءات التطوير والإنتاج كثيرًا. في التطوير نريد خرائط مصدر قوية وخادمًا محليًا مع إعادة تحميل حية أو استبدال الوحدات الساخن. أما في الإنتاج فتتحول أهدافنا إلى التركيز على حزم مصغّرة، وخرائط مصدر أخف وزنًا، وأصول محسّنة لتحسين وقت التحميل. وبوجود هذا الفصل المنطقي، نوصي عادة بكتابة إعدادات webpack منفصلة لكل بيئة.

مع أننا سنفصل الأجزاء الخاصة بالإنتاج والتطوير، لاحظ أننا سنبقي إعدادًا «مشتركًا» للحفاظ على مبدأ DRY. لدمج هذه الإعدادات معًا، سنستخدم أداة مساعدة تسمى webpack-merge. بوجود الإعداد «المشترك»، لن نحتاج إلى تكرار الكود داخل الإعدادات الخاصة بكل بيئة.

لنبدأ بتثبيت webpack-merge وفصل الأجزاء التي عملنا عليها بالفعل في الأدلة السابقة:

npm install --save-dev webpack-merge

project

  webpack-demo
  ├── package.json
  ├── package-lock.json
- ├── webpack.config.js
+ ├── webpack.common.js
+ ├── webpack.dev.js
+ ├── webpack.prod.js
  ├── /dist
  ├── /src
  │   ├── index.js
  │   └── math.js
  └── /node_modules

webpack.common.js

+ import path from 'node:path';
+ import { fileURLToPath } from 'node:url';
+ import HtmlWebpackPlugin from 'html-webpack-plugin';
+
+ const __filename = fileURLToPath(import.meta.url);
+ const __dirname = path.dirname(__filename);
+
+ export default {
+   entry: {
+     app: './src/index.js',
+   },
+   plugins: [
+     new HtmlWebpackPlugin({
+       title: 'Production',
+     }),
+   ],
+   output: {
+     filename: '[name].bundle.js',
+     path: path.resolve(__dirname, 'dist'),
+     clean: true,
+   },
+ };

webpack.dev.js

+ import { merge } from 'webpack-merge';
+ import common from './webpack.common.js';
+
+ export default merge(common, {
+   mode: 'development',
+   devtool: 'inline-source-map',
+   devServer: {
+     static: './dist',
+   },
+ });

webpack.prod.js

+ import { merge } from 'webpack-merge';
+ import common from './webpack.common.js';
+
+ export default merge(common, {
+   mode: 'production',
+ });

في webpack.common.js أصبح لدينا الآن إعدادا entry وoutput، وأضفنا أي ملحقات مطلوبة لكلتا البيئتين. في webpack.dev.js عيّنا mode إلى development. كذلك أضفنا خيار devtool الموصى به لتلك البيئة، وهو خرائط مصدر قوية، بالإضافة إلى إعداد devServer. وأخيرًا، في webpack.prod.js، عُيّن mode إلى production، مما يحمّل MinimizerPlugin الذي قُدّم أول مرة في دليل إزالة الكود غير المستخدم.

لاحظ استخدام استدعاءات merge() في الإعدادات الخاصة بكل بيئة لتضمين الإعداد المشترك داخل webpack.dev.js وwebpack.prod.js. توفر أداة webpack-merge مجموعة من الميزات المتقدمة للدمج، لكننا لن نحتاج إلى أي منها في حالتنا.

سكربتات NPM

الآن، لنعدّل سكربتات npm لاستخدام ملفات الإعداد الجديدة. بالنسبة إلى سكربت start، الذي يشغّل webpack-dev-server، سنستخدم webpack.dev.js، وبالنسبة إلى سكربت build، الذي يشغّل webpack لإنشاء بناء إنتاج، سنستخدم webpack.prod.js:

package.json

  {
    "name": "development",
    "version": "1.0.0",
    "description": "",
    "main": "src/index.js",
    "scripts": {
-     "start": "webpack serve --open",
+     "start": "webpack serve --open --config webpack.dev.js",
-     "build": "webpack"
+     "build": "webpack --config webpack.prod.js"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "devDependencies": {
      "css-loader": "^7.1.3",
      "csv-loader": "^3.0.5",
      "express": "^5.2.1",
      "html-webpack-plugin": "^5.6.6",
      "style-loader": "^4.0.0",
      "webpack": "^5.105.0",
      "webpack-cli": "^7.0.0",
      "webpack-dev-middleware": "^8.0.3",
      "webpack-dev-server": "^5.2.3",
      "webpack-merge": "^6.0.1",
      "xml-loader": "^1.2.1"
    }
  }

يمكنك تشغيل هذه السكربتات وملاحظة كيف يتغير الخرج بينما نواصل الإضافة إلى إعداد الإنتاج.

تحديد الوضع

تعتمد كثير من المكتبات على المتغير process.env.NODE_ENV لتحديد ما ينبغي تضمينه في المكتبة. على سبيل المثال، عندما لا تكون قيمة process.env.NODE_ENV مضبوطة على 'production'، قد تضيف بعض المكتبات تسجيلًا واختبارات إضافية لتسهيل التصحيح. أما مع ضبط process.env.NODE_ENV إلى 'production'، فقد تحذف أو تضيف أجزاء كبيرة من الكود لتحسين طريقة التشغيل للمستخدمين الفعليين. منذ webpack v4، يؤدي تحديد mode إلى إعداد process.env.NODE_ENV تلقائيًا عبر DefinePlugin:

webpack.prod.js

  import { merge } from 'webpack-merge';
  import common from './webpack.common.js';

  export default merge(common, {
    mode: 'production',
  });

إذا كنت تستخدم مكتبة مثل react، فينبغي أن تلاحظ انخفاضًا ملحوظًا في حجم الحزمة بعد إضافة DefinePlugin. ولاحظ أيضًا أن أي كود محلي داخل /src يمكنه الاعتماد على هذا المتغير كذلك، لذا سيكون الفحص التالي صالحًا:

src/index.js

  import { cube } from './math.js';
+
+ if (process.env.NODE_ENV !== 'production') {
+   console.log('Looks like we are in development mode!');
+ }

  function component() {
    const element = document.createElement('pre');

    element.innerHTML = [
      'Hello webpack!',
      '5 cubed is equal to ' + cube(5)
    ].join('\n\n');

    return element;
  }

  document.body.appendChild(component());

التصغير

سيقوم webpack v4+ بتصغير الكود افتراضيًا في وضع الإنتاج.

لاحظ أنه مع أن MinimizerPlugin نقطة بداية ممتازة للتصغير ويُستخدم افتراضيًا، فهناك خيارات أخرى متاحة:

إذا قررت تجربة ملحق تصغير آخر، فتأكد من أن اختيارك الجديد يحذف أيضًا الكود الميت كما هو موضح في دليل إزالة الكود غير المستخدم، وقدّمه عبر optimization.minimizer.

خرائط المصدر

نشجعك على تفعيل خرائط المصدر في الإنتاج، لأنها مفيدة للتصحيح وكذلك لتشغيل اختبارات القياس. ومع ذلك، ينبغي اختيار خيار بسرعة بناء معقولة وموصى به للاستخدام في الإنتاج، راجع devtool. في هذا الدليل سنستخدم خيار source-map في الإنتاج بدلًا من inline-source-map الذي استخدمناه في التطوير:

webpack.prod.js

  import { merge } from 'webpack-merge';
  import common from './webpack.common.js';

  export default merge(common, {
    mode: 'production',
+   devtool: 'source-map',
  });

تصغير CSS

من المهم جدًا تصغير CSS للإنتاج. يرجى مراجعة قسم التصغير للإنتاج.

بدائل CLI

يمكن تعيين كثير من الخيارات الموضحة أعلاه كوسيطات في سطر الأوامر. على سبيل المثال، يمكن تعيين optimization.minimize باستخدام --optimization-minimize، ويمكن تعيين mode باستخدام --mode. شغّل npx webpack --help=verbose للحصول على قائمة كاملة بوسيطات CLI.

مع أن هذه الطرق المختصرة مفيدة، فإننا نوصي بتعيين هذه الخيارات داخل ملف إعداد webpack للحصول على قابلية ضبط أكبر.

Edit this page·

1 Contributor

arabpolice