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

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

بدايةً من الإصدار 9 والإصدارات الأحدث، تم تحسين واجهة برمجة التطبيقات النموذجية الخاصة بـ Firebase JavaScript للتوافق مع ميزات التحسين الخاصة بأدوات تجميع الوحدات بهدف تقليل مقدار رموز 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 والدمج والإنشاء.

البدء

يتطلب هذا الدليل تثبيت 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 مع حزمة الويب

ولا تحتاج إلى ضبط أيّ من تطبيقات Firebase وحِزم الويب. ويتناول هذا القسم الإعداد العام لحزمة الويب.

الخطوة الأولى هي تثبيت 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 للإنتاج، يمكنك الاطّلاع على المستندات الرسمية حول إعداد الضبط "mode".

استخدام Firebase من خلال ميزة البيانات المجمّعة

ولا تحتاج إلى ضبط أيّ من التطبيقات وعملية الدمج على Firebase. يتناول هذا القسم إعدادات عامة لتجميع البيانات.

تتمثّل الخطوة الأولى في تثبيت أداة دمج القنوات ومكوّن إضافي يُستخدم لربط عمليات الاستيراد بالتبعيات التي تم تثبيتها باستخدام 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 لتنفيذ عملية إنشاء البيانات المجمّعة. افتح ملف package.json وأضف زوج قيمة المفتاح التالي إلى الكائن "scripts".

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

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

npm run build

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

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

استخدام Firebase من خلال الإنشاء

ما مِن حاجة إلى ضبط إعدادات محدَّدة لتطبيقات Firebase وإنشاؤها. يتناول هذا القسم تهيئة إنشاء عامة.

الخطوة الأولى هي تثبيت 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 لتنفيذ عملية الإنشاء. افتح ملف package.json وأضف زوج القيمة المفتاح التالي إلى الكائن "scripts".

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

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

لمزيد من المعلومات حول تحسين عملية الإنشاء للإنتاج، يُرجى الاطّلاع على مستندات الشركة الرسمية حول تصغير البيانات والتحسينات الأخرى.