搭配 Firebase 使用模組組合器

JavaScript 模組套件匯入器可執行許多工作,但其中最實用的功能之一,就是能夠在程式碼集區中新增及使用外部程式庫。模組套件匯入器會讀取程式碼中的匯入路徑,並將應用程式專屬程式碼與匯入的程式庫程式碼結合 (套件)。

自第 9 版起,Firebase JavaScript 模組 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.
 */

從程式庫中移除未使用的程式碼的程序稱為搖樹。手動移除這段程式碼會耗費大量時間,且容易出錯,但模組套件處理器可自動執行這項移除作業。

JavaScript 生態系統中有多個優質的模組套件封裝器。本指南將著重於說明如何搭配使用 webpackRollupesbuild 使用 Firebase。

開始使用

本指南要求您在開發環境中安裝 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 installnpm i 指令新增依附元件。

npm i firebase

執行 npm i firebase 時,安裝程序會更新 package.json,將 Firebase 列為依附元件:

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

鍵是程式庫的名稱,值則是所使用的版本。版本值相當靈活,可接受多種值。這就是所謂的語意版本管理或 semver。如要進一步瞭解 semver,請參閱 npm 關於語意版本編號的指南

來源和建構資料夾

您編寫的程式碼會由模組套件處理器讀取及處理,然後輸出為新檔案或一組檔案。請務必將這兩種檔案分開。模組套件讀取及處理的程式碼稱為「來源」程式碼。這些檔案的輸出結果稱為已建構或「dist」(發布) 程式碼。

在程式碼集的常見設定中,原始碼會儲存在名為 src 的資料夾中,而已建構的程式碼則會儲存在名為 dist 的資料夾中。

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


- dist
 |_ bundle.js

在上述範例檔案結構中,請考慮 index.js 同時匯入 animations.jsdatalist.js。當模組套件處理原始碼時,會在 dist 資料夾中產生 bundle.js 檔案。bundle.jssrc 資料夾中的檔案和匯入的任何程式庫組合。

如果您使用 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 檔案會開始匯入應用程式所需的所有程式碼,因此會視為進入點。模組套件匯入器會使用這個進入點檔案,開始套件匯入程序。

搭配 webpack 使用 Firebase

Firebase 應用程式和 webpack 不需要進行任何特定設定。本節將介紹一般 webpack 設定

第一步是從 npm 安裝 webpack 做為開發依附元件。

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 載入「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 的檔案,其中包含已內含應用程式和依附元件程式碼的檔案。

如要進一步瞭解如何針對正式版最佳化 webpack 建構作業,請參閱官方文件中的「模式」設定

搭配使用 Firebase 和 Rollup

Firebase 應用程式和 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 指令稿,以便執行匯集建構作業。開啟 package.json 檔案,然後將下列鍵/值組合新增至 "scripts" 物件。

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

如要執行匯總並產生建構資料夾,請執行下列指令。

npm run build

最後,請檢查 dist 建構資料夾。其中應包含名為 bundle.js 的檔案,其中包含已內含應用程式和依附元件程式碼的檔案。

如要進一步瞭解如何針對實際發布作業最佳化 Rollup 建構作業,請參閱官方文件,瞭解用於正式版建構的插件

搭配 esbuild 使用 Firebase

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 載入「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 的檔案,其中包含已內含應用程式和依附元件程式碼的檔案。

如要進一步瞭解如何為正式版最佳化 esbuild,請參閱官方文件,瞭解縮減和其他最佳化