การใช้ Bundler โมดูลกับ Firebase

JavaScript Module Bundler ทำได้หลายอย่าง แต่ฟีเจอร์ที่มีประโยชน์มากที่สุดอย่างหนึ่งคือความสามารถในการเพิ่มและใช้ไลบรารีภายนอกในฐานของโค้ด Module Bundler จะอ่านเส้นทางการนำเข้าในโค้ดและรวม (Bundle) โค้ดเฉพาะของแอปพลิเคชันเข้ากับโค้ดไลบรารีที่นำเข้า

Firebase JavaScript Modular API เวอร์ชัน 9 ขึ้นไปได้รับการเพิ่มประสิทธิภาพให้ทำงานร่วมกับฟีเจอร์การเพิ่มประสิทธิภาพของ Module Bundler เพื่อลดปริมาณโค้ด 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.
 */

กระบวนการกำจัดโค้ดที่ไม่ได้ใช้ออกจากไลบรารีนี้เรียกว่า Tree Shaking การนำโค้ดนี้ออกด้วยตนเองจะใช้เวลานานมากและมีโอกาสเกิดข้อผิดพลาดได้ง่าย แต่ Module Bundler สามารถทำให้การนำออกนี้เป็นไปโดยอัตโนมัติ

ระบบนิเวศ JavaScript มี Module Bundler คุณภาพสูงมากมาย คู่มือนี้มุ่งเน้นที่การใช้ Firebase กับ Webpack, Rollup และ Esbuild

เริ่มต้นใช้งาน

คู่มือนี้กำหนดให้คุณต้องติดตั้ง npm ในสภาพแวดล้อมในการพัฒนาซอฟต์แวร์ npm ใช้เพื่อติดตั้งและจัดการทรัพยากร Dependency (ไลบรารี) หากต้องการติดตั้ง 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 เป็นทรัพยากร Dependency

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

คีย์คือชื่อของไลบรารี และค่าคือเวอร์ชันที่จะใช้ ค่าเวอร์ชันมีความยืดหยุ่นและยอมรับค่าได้หลากหลาย ซึ่งเรียกว่าการกำหนดเวอร์ชันเชิงความหมายหรือ Semver ดูข้อมูลเพิ่มเติมเกี่ยวกับ Semver, ดูคู่มือการกำหนดเวอร์ชันเชิงความหมายของ npm

โฟลเดอร์ต้นทางเทียบกับโฟลเดอร์บิลด์

Module Bundler จะอ่านและประมวลผลโค้ดที่คุณเขียน จากนั้นส่งออกเป็นไฟล์ใหม่หรือชุดไฟล์ คุณควรแยกไฟล์ 2 ประเภทนี้ออกจากกัน โค้ดที่ Module Bundler อ่านและประมวลผลเรียกว่าโค้ด "ต้นทาง" ส่วนไฟล์ที่ส่งออกเรียกว่าโค้ดบิลด์หรือโค้ด "dist" (การเผยแพร่)

การตั้งค่าที่พบบ่อยในฐานของโค้ดคือการจัดเก็บโค้ดต้นทางไว้ในโฟลเดอร์ที่ชื่อว่า src และโค้ดบิลด์ไว้ในโฟลเดอร์ที่ชื่อว่า dist

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


- dist
 |_ bundle.js

ในโครงสร้างไฟล์ตัวอย่างด้านบน ให้พิจารณาว่า index.js นำเข้าทั้ง animations.js และ datalist.js เมื่อ Module Bundler ประมวลผลโค้ดต้นทาง ระบบจะสร้างไฟล์ bundle.js ในโฟลเดอร์ dist bundle.js เป็นการรวมไฟล์ในโฟลเดอร์ src และไลบรารีที่นำเข้าด้วย

หากคุณใช้ระบบควบคุมแหล่งที่มา เช่น Git โดยทั่วไปแล้วจะละเว้นโฟลเดอร์ dist เมื่อจัดเก็บโค้ดนี้ไว้ในที่เก็บข้อมูลหลัก

จุดแรกเข้า

Module Bundler ทั้งหมดมีแนวคิดเรื่องจุดแรกเข้า คุณสามารถนึกภาพแอปพลิเคชันเป็นโครงสร้างไฟล์แบบต้นไม้ ไฟล์หนึ่งนำเข้าโค้ดจากอีกไฟล์หนึ่ง และอื่นๆ ซึ่งหมายความว่าไฟล์หนึ่งจะเป็นรูทของโครงสร้างแบบต้นไม้ ไฟล์นี้เรียกว่าจุดแรกเข้า

กลับไปดูตัวอย่างโครงสร้างไฟล์ก่อนหน้า

- 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 ถือเป็นจุดแรกเข้าเนื่องจากเป็นจุดเริ่มต้นของการนำเข้าโค้ดทั้งหมดที่จำเป็นสำหรับแอปพลิเคชัน Module Bundler ใช้ไฟล์จุดแรกเข้านี้เพื่อเริ่มกระบวนการรวม

การใช้ 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 เป็นทรัพยากร Dependency แล้ว

npm i firebase

จากนั้นเริ่มต้น Firebase ในฐานของโค้ด โค้ดต่อไปนี้จะนำเข้าและเริ่มต้น Firebase ในไฟล์จุดแรกเข้า และใช้ Firestore Lite เพื่อโหลดเอกสาร "city"

// 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 ซึ่งมีโค้ดแอปพลิเคชันและโค้ดทรัพยากร Dependency ที่รวมไว้

ดูข้อมูลเพิ่มเติมเกี่ยวกับการเพิ่มประสิทธิภาพบิลด์ 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 เพื่อโหลดเอกสาร "city"

// 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 ซึ่งมีโค้ดแอปพลิเคชันและโค้ดทรัพยากร Dependency ที่รวมไว้

ดูข้อมูลเพิ่มเติมเกี่ยวกับการเพิ่มประสิทธิภาพบิลด์ Rollup สำหรับการใช้งานจริงได้ใน เอกสารอย่างเป็นทางการ เกี่ยวกับปลั๊กอินสำหรับบิลด์การใช้งานจริง

การใช้ Firebase กับ Esbuild

แอป Firebase และ Esbuild ไม่จำเป็นต้องมีการกำหนดค่าที่เฉพาะเจาะจง ส่วนนี้ครอบคลุมการกำหนดค่า Esbuild ทั่วไป

ขั้นตอนแรกคือการติดตั้ง esbuild เป็นทรัพยากร Dependency สำหรับการพัฒนาซอฟต์แวร์

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 เพื่อโหลดเอกสาร "city"

// 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 ซึ่งมีโค้ดแอปพลิเคชันและโค้ดทรัพยากร Dependency ที่รวมไว้

ดูข้อมูลเพิ่มเติมเกี่ยวกับการเพิ่มประสิทธิภาพ Esbuild สำหรับการใช้งานจริงได้ในเอกสารอย่างเป็นทางการ เกี่ยวกับการลดขนาดและการเพิ่มประสิทธิภาพอื่นๆ