استخدام أدوات حزم الوحدات مع Firebase

يمكن لحِزم وحدات JavaScript تنفيذ العديد من المهام، ولكن من بين أكثر ميزاتها فائدةً إمكانية إضافة مكتبات خارجية واستخدامها في قاعدة الرموز البرمجية. تقرأ حِزم الوحدات مسارات الاستيراد في الرموز البرمجية وتدمج (تحزم) الرموز البرمجية الخاصة بتطبيقك مع رموز المكتبة المستورَدة.

اعتبارًا من الإصدار 9 والإصدارات الأحدث، تم تحسين واجهة برمجة التطبيقات المعيارية JavaScript من Firebase للعمل مع ميزات التحسين في حِزم الوحدات من أجل تقليل حجم رموز Firebase المضمّنة في الإصدار النهائي.

import { initializeApp } from 'firebase/app';
import { getAuth, onAuthStateChanged, getRedirectResult } from 'firebase/auth';

const firebaseApp = initializeApp({ /* config */ });
const auth = getAuth(firebaseApp);
onAuthStateChanged(auth, user => { /* check status */ });

/**
 * getRedirectResult is unused and should not be included in the code base.
 * In addition, there are many other functions within firebase/auth that are
 * not imported and therefore should not be included as well.
 */

تُعرف عملية إزالة الرموز البرمجية غير المستخدَمة من مكتبة باسم "تجريد الشجرة". ستكون إزالة هذه الرموز البرمجية يدويًا عملية تستغرق وقتًا طويلاً وعرضة للأخطاء، ولكن يمكن لحِزم الوحدات أتمتة هذه الإزالة.

تتوفّر العديد من حِزم الوحدات العالية الجودة في النظام الشامل JavaScript. يركّز هذا الدليل على استخدام Firebase مع webpack و Rollup و esbuild.

البدء

يتطلب هذا الدليل تثبيت npm في بيئة التطوير. تُستخدم npm لتثبيت التبعيات (المكتبات) وإدارتها. لتثبيت npm، ثبِّت Node.js الذي يتضمّن npm تلقائيًا.

يتم إعداد معظم المطوّرين بشكل صحيح بعد تثبيت Node.js. ومع ذلك، يواجه العديد من المطوّرين مشاكل شائعة عند إعداد بيئتهم. إذا واجهت أي أخطاء، تأكَّد من أنّ بيئتك تتضمّن واجهة سطر الأوامر npm وأنّ لديك الأذونات المناسبة كي لا تضطر إلى تثبيت الحِزم بصفتك مشرفًا باستخدام الأمر sudo.

ملف package.json وتثبيت Firebase

بعد تثبيت npm، عليك إنشاء ملف package.json في جذر مشروعك المحلي. أنشِئ هذا الملف باستخدام أمر npm التالي:

npm init

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

{
  "name": "your-package-name",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {

  }
}

هذا الملف مسؤول عن العديد من المهام المختلفة. وهو ملف مهم يجب التعرّف عليه إذا أردت معرفة المزيد عن حزم الوحدات وإنشاء رموز JavaScript البرمجية بشكل عام. الجزء المهم في هذا الدليل هو العنصر "dependencies" سيحتوي هذا العنصر على زوج من المفتاح والقيمة للمكتبة التي ثبَّتها والإصدار الذي تستخدمه.

تتم إضافة التبعيات من خلال الأمر npm install أو npm i.

npm i firebase

عند تنفيذ npm i firebase، ستعدِّل عملية التثبيت ملف package.json لإدراج Firebase كإحدى التبعيات:

  "dependencies": {
    "firebase": "^9.0.0"
  },

المفتاح هو اسم المكتبة والقيمة هي الإصدار الذي سيتم استخدامه. قيمة الإصدار مرنة ويمكن أن تقبل مجموعة من القيم. يُعرف ذلك باسم تحديد الإصدارات الدلالية أو semver. لمزيد من المعلومات عن semver، اطّلِع على دليل npm حول تحديد الإصدارات الدلالية.

المجلدات المصدر مقابل مجلدات الإصدار

يقرأ حازم الوحدات الرموز البرمجية التي تكتبها ويعالجها ثم يعرضها كملف جديد أو مجموعة من الملفات. من المهم فصل هذين النوعَين من الملفات. تُعرف الرموز البرمجية التي تقرأها حِزم الوحدات وتعالجها باسم رموز "المصدر" البرمجية. أما الملفات التي تعرضها فتُعرف باسم الرموز البرمجية التي تم إنشاؤها أو "التوزيع".

من الإعدادات الشائعة في قواعد الرموز البرمجية تخزين رموز المصدر البرمجية في مجلد باسم src والرموز البرمجية التي تم إنشاؤها في مجلد باسم dist.

- src
 |_ index.js
 |_ animations.js
 |_ datalist.js


- dist
 |_ bundle.js

في مثال بنية الملف أعلاه، لنفترض أنّ index.js يستورد كلاً من animations.js وdatalist.js. عندما يعالج حازم الوحدات رموز المصدر البرمجية، سينشئ ملف bundle.js في المجلد dist. إنّ bundle.js هو مزيج من الملفات في المجلد src وأي مكتبات يتم استيرادها أيضًا.

إذا كنت تستخدم أنظمة التحكّم في المصدر مثل Git، من الشائع تجاهل المجلد dist عند تخزين هذه الرموز البرمجية في المستودع الرئيسي.

نقاط الإدخال

تتضمّن جميع حِزم الوحدات مفهوم نقطة الإدخال. يمكنك اعتبار تطبيقك شجرة من الملفات. يستورد أحد الملفات رموزًا برمجية من ملف آخر وهكذا. هذا يعني أنّ أحد الملفات سيكون جذر الشجرة. يُعرف هذا الملف باسم نقطة الإدخال.

لنرجع إلى مثال بنية الملف السابق.

- src
 |_ index.js
 |_ animations.js
 |_ datalist.js


- dist
 |_ bundle.js
// src/index.js
import { animate } from './animations';
import { createList } from './datalist';

// This is not real code, but for example purposes only
const theList = createList('users/123/tasks');
theList.addEventListener('loaded', event => {
  animate(theList);
});

يُعدّ الملف src/index.js نقطة الإدخال لأنّه يبدأ عمليات استيراد جميع الرموز البرمجية المطلوبة للتطبيق. تستخدم حِزم الوحدات ملف نقطة الإدخال هذا لبدء عملية الحزم.

استخدام Firebase مع webpack

ما مِن إعدادات محدّدة مطلوبة لتطبيقات Firebase وwebpack. يغطّي هذا القسم إعدادًا عامًا لـ webpack.

الخطوة الأولى هي تثبيت webpack من npm كإحدى تبعيات التطوير.

npm i webpack webpack-cli -D

أنشِئ ملفًا باسم webpack.config.js في جذر مشروعك المحلي وأضِف الرموز البرمجية التالية.

const path = require('path');

module.exports = {
  // The entry point file described above
  entry: './src/index.js',
  // The location of the build folder described above
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  // Optional and for development only. This provides the ability to
  // map the built code back to the original source format when debugging.
  devtool: 'eval-source-map',
};

بعد ذلك، تأكَّد من تثبيت Firebase كإحدى التبعيات.

npm i firebase

ثم ابدأ Firebase في قاعدة الرموز البرمجية. تستورد الرموز البرمجية التالية Firebase وتبدأها في ملف نقطة إدخال وتستخدم Firestore Lite لتحميل مستند "مدينة".

// src/index.js
import { initializeApp } from 'firebase/app';
import { getFirestore, doc, getDoc } from 'firebase/firestore/lite';

const firebaseApp = initializeApp({ /* config */ });
const db = getFirestore(firebaseApp);

async function loadCity(name) {
  const cityDoc = doc(db, `cities/${name}`);
  const snapshot = await getDoc(cityDoc);
  return {
    id: snapshot.id,
    ...snapshot.data(),
  };
}

الخطوة التالية هي إضافة نص برمجي npm لتنفيذ إصدار webpack. افتح الملف package.json وأضِف زوج المفتاح والقيمة التالي إلى العنصر "scripts".

  "scripts": {
    "build": "webpack --mode=development"
  },

لتنفيذ webpack وإنشاء مجلد الإصدار، نفِّذ الأمر التالي.

npm run build

أخيرًا، تحقَّق من مجلد الإصدار dist. يجب أن يحتوي على ملف باسم bundle.js يتضمّن تطبيقك المحزوم ورموز التبعيات البرمجية.

لمزيد من المعلومات عن تحسين إصدار webpack للإنتاج، اطّلِع على المستندات الرسمية حول إعدادات "الوضع".

استخدام Firebase مع Rollup

ما مِن إعدادات محدّدة مطلوبة لتطبيقات Firebase وRollup. يغطّي هذا القسم إعدادًا عامًا لـ Rollup.

الخطوة الأولى هي تثبيت Rollup ومكوّن إضافي يُستخدم لربط عمليات الاستيراد بالتبعيات المثبَّتة باستخدام npm.

npm i rollup @rollup/plugin-node-resolve -D

أنشِئ ملفًا باسم rollup.config.js في جذر مشروعك المحلي وأضِف الرموز البرمجية التالية.

import { nodeResolve } from '@rollup/plugin-node-resolve';

export default {
  // the entry point file described above
  input: 'src/index.js',
  // the output for the build folder described above
  output: {
    file: 'dist/bundle.js',
    // Optional and for development only. This provides the ability to
    // map the built code back to the original source format when debugging.
    sourcemap: 'inline',
    // Configure Rollup to convert your module code to a scoped function
    // that "immediate invokes". See the Rollup documentation for more
    // information: https://rollupjs.org/guide/en/#outputformat
    format: 'iife'
  },
  // Add the plugin to map import paths to dependencies
  // installed with npm
  plugins: [nodeResolve()]
};

ثم ابدأ Firebase في قاعدة الرموز البرمجية. تستورد الرموز البرمجية التالية Firebase وتبدأها في ملف نقطة إدخال وتستخدم Firestore Lite لتحميل مستند "مدينة".

// src/index.js
import { initializeApp } from 'firebase/app';
import { getFirestore, doc, getDoc } from 'firebase/firestore/lite';

const firebaseApp = initializeApp({ /* config */ });
const db = getFirestore(firebaseApp);

async function loadCity(name) {
  const cityDoc = doc(db, `cities/${name}`);
  const snapshot = await getDoc(cityDoc);
  return {
    id: snapshot.id,
    ...snapshot.data(),
  };
}

الخطوة التالية هي إضافة نص برمجي npm لتنفيذ إصدار Rollup. افتح الملف package.json وأضِف زوج المفتاح والقيمة التالي إلى العنصر "scripts".

  "scripts": {
    "build": "rollup -c rollup.config.js"
  },

لتنفيذ Rollup وإنشاء مجلد الإصدار، نفِّذ الأمر التالي.

npm run build

أخيرًا، تحقَّق من مجلد الإصدار dist. يجب أن يحتوي على ملف باسم bundle.js يتضمّن تطبيقك المحزوم ورموز التبعيات البرمجية.

لمزيد من المعلومات عن تحسين إصدار Rollup للإنتاج، اطّلِع على المستندات الرسمية حول المكوّنات الإضافية لإصدارات الإنتاج.

استخدام Firebase مع esbuild

ما مِن إعدادات محدّدة مطلوبة لتطبيقات Firebase وesbuild. يغطّي هذا القسم إعدادًا عامًا لـ esbuild.

الخطوة الأولى هي تثبيت esbuild كإحدى تبعيات التطوير.

npm i esbuild -D

أنشِئ ملفًا باسم esbuild.config.js في جذر مشروعك المحلي وأضِف الرموز البرمجية التالية.

require('esbuild').build({
  // the entry point file described above
  entryPoints: ['src/index.js'],
  // the build folder location described above
  outfile: 'dist/bundle.js',
  bundle: true,
  // Replace with the browser versions you need to target
  target: ['chrome60', 'firefox60', 'safari11', 'edge20'],
  // Optional and for development only. This provides the ability to
  // map the built code back to the original source format when debugging.
  sourcemap: 'inline',
}).catch(() => process.exit(1))

ثم ابدأ Firebase في قاعدة الرموز البرمجية. تستورد الرموز البرمجية التالية Firebase وتبدأها في ملف نقطة إدخال وتستخدم Firestore Lite لتحميل مستند "مدينة".

// src/index.js
import { initializeApp } from 'firebase/app';
import { getFirestore, doc, getDoc } from 'firebase/firestore/lite';

const firebaseApp = initializeApp({ /* config */ });
const db = getFirestore(firebaseApp);

async function loadCity(name) {
  const cityDoc = doc(db, `cities/${name}`);
  const snapshot = await getDoc(cityDoc);
  return {
    id: snapshot.id,
    ...snapshot.data(),
  };
}

الخطوة التالية هي إضافة نص برمجي npm لتنفيذ esbuild. افتح الملف package.json وأضِف زوج المفتاح والقيمة التالي إلى العنصر "scripts".

  "scripts": {
    "build": "node ./esbuild.config.js"
  },

أخيرًا، تحقَّق من مجلد الإصدار dist. يجب أن يحتوي على ملف باسم bundle.js يتضمّن تطبيقك المحزوم ورموز التبعيات البرمجية.

لمزيد من المعلومات عن تحسين esbuild للإنتاج، اطّلِع على المستندات الرسمية حول التصغير والتحسينات الأخرى.