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

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

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

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

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

npm i firebase

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

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

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

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

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

การตั้งค่าทั่วไปในฐานโค้ดคือการเก็บซอร์สโค้ดไว้ในโฟลเดอร์ชื่อ 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 เป็น Dependency แล้ว

npm i firebase

จากนั้นเริ่มต้น Firebase ในฐานโค้ด โค้ดต่อไปนี้จะนําเข้าและเริ่มต้น Firebase ในไฟล์ Entry Point และใช้ 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 build โดยควรมีไฟล์ชื่อ bundle.js ที่มีแอปพลิเคชันและโค้ดที่ต้องพึ่งพาซึ่งรวมไว้ด้วยกัน

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

การใช้ 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 ในไฟล์ Entry Point และใช้ 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"
  },

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

npm run build

สุดท้าย ให้ตรวจสอบโฟลเดอร์ dist build โดยควรมีไฟล์ชื่อ bundle.js ที่มีแอปพลิเคชันและโค้ดที่ต้องพึ่งพาซึ่งรวมไว้ด้วยกัน

ดูข้อมูลเพิ่มเติมเกี่ยวกับการเพิ่มประสิทธิภาพบิลด์ 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 ในไฟล์ Entry Point และใช้ 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 build โดยควรมีไฟล์ชื่อ bundle.js ที่มีแอปพลิเคชันและโค้ดที่ต้องพึ่งพาซึ่งรวมไว้ด้วยกัน

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