استخدام حزم الوحدات النمطية مع 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 و Rollup و esbuild .

البدء

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

يتم إعداد معظم المطورين بشكل صحيح بمجرد تثبيت Node.js. ومع ذلك، هناك مشكلات شائعة يواجهها العديد من المطورين عند إعداد بيئتهم. إذا واجهت أي أخطاء، فتأكد من أن بيئتك تحتوي على npm CLI وأن لديك الأذونات المناسبة التي تم إعدادها حتى لا تضطر إلى تثبيت الحزم كمسؤول باستخدام الأمر 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 وحزمة الويب. يغطي هذا القسم التكوين العام لحزمة الويب .

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

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

لتشغيل حزمة الويب وإنشاء مجلد البناء، قم بتشغيل الأمر التالي.

npm run build

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

لمزيد من المعلومات حول تحسين إنشاء حزمة الويب الخاصة بك للإنتاج، راجع وثائقهم الرسمية حول إعداد تكوين "الوضع" .

استخدام Firebase مع الإظهار

لا توجد حاجة إلى تكوين محدد لتطبيقات Firebase ومجموعة التحديثات. يغطي هذا القسم التكوين العام للمجموع.

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

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

لتشغيل مجموعة التحديثات وإنشاء مجلد البناء، قم بتشغيل الأمر التالي.

npm run build

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

لمزيد من المعلومات حول تحسين إصدار مجموعة التحديثات الخاص بك للإنتاج، راجع وثائقهم الرسمية حول المكونات الإضافية لإصدارات الإنتاج .

استخدام 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 build. يجب أن يحتوي على ملف باسم bundle.js يحتوي على التطبيق المجمع ورمز التبعية.

لمزيد من المعلومات حول تحسين esbuild للإنتاج، راجع وثائقهم الرسمية حول التصغير والتحسينات الأخرى .