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

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

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

กระบวนการกำจัดโค้ดที่ไม่ได้ใช้ออกจากไลบรารีนี้เรียกว่าการเขย่าต้นไม้ การนำโค้ดนี้ออกด้วยตนเองอาจใช้เวลานานสุดๆ และเกิดข้อผิดพลาดได้ง่าย แต่ Bundler โมดูลสามารถนำโค้ดนี้ออกโดยอัตโนมัติได้

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

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

คู่มือนี้กำหนดให้คุณติดตั้ง 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" ออบเจ็กต์นี้จะเก็บคู่คีย์-ค่าของไลบรารีที่คุณติดตั้งและเวอร์ชันที่กำลังใช้อยู่

การเพิ่มทรัพยากร Dependency ทำได้ผ่านคำสั่ง npm install หรือ npm i

npm i firebase

เมื่อคุณเรียกใช้ npm i firebase กระบวนการติดตั้งจะอัปเดต package.json เพื่อแสดง Firebase เป็นทรัพยากร Dependency ดังนี้

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

คีย์คือชื่อของไลบรารีและค่าคือเวอร์ชันที่จะใช้ ค่าเวอร์ชันมีความยืดหยุ่นและยอมรับช่วงของค่าได้ วิธีนี้เรียกว่าการกำหนดเวอร์ชันทางอรรถศาสตร์หรือ การคัดแยกเนื้อหา หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับ Semver โปรดดูคำแนะนำของ NPM เกี่ยวกับการกำหนดเวอร์ชันทางอรรถศาสตร์

โฟลเดอร์ต้นทางและการสร้าง

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

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

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


- dist
 |_ bundle.js

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

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

จุดแรกเข้า

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

การใช้ Firebase กับ Webpack

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

ขั้นตอนแรกคือการติดตั้ง Webpack จาก npm เป็นทรัพยากร Dependency ของการพัฒนา

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 แบบควบรวม

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

ขั้นตอนแรกคือการติดตั้งรายงานและปลั๊กอินที่ใช้เพื่อแมปการนำเข้ากับทรัพยากร Dependency ที่ติดตั้งด้วย 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 เพื่อเรียกใช้บิลด์การรวม เปิดไฟล์ package.json และเพิ่มคู่คีย์-ค่าต่อไปนี้ลงในออบเจ็กต์ "scripts"

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

หากต้องการเรียกใช้รายงานและสร้างโฟลเดอร์บิลด์ ให้เรียกใช้คำสั่งต่อไปนี้

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 สำหรับเวอร์ชันที่ใช้งานจริงได้ในเอกสารประกอบอย่างเป็นทางการของบริษัทเกี่ยวกับการลดขนาดและการเพิ่มประสิทธิภาพอื่นๆ