使用產生的 Web SDK

Firebase SQL Connect 用戶端 SDK 可讓您直接從 Firebase 應用程式呼叫伺服器端查詢和變異。在設計要部署至 SQL Connect 服務的結構定義、查詢和變異時,您會同時產生自訂用戶端 SDK。接著,將這個 SDK 的方法整合至用戶端邏輯。

如先前所述,請務必注意,SQL Connect查詢和變動並非由用戶端程式碼提交,而是在伺服器上執行。相反地,部署時,SQL Connect 作業會儲存在伺服器上,例如 Cloud Functions。這表示您需要部署相應的用戶端變更,以免影響現有使用者 (例如使用舊版應用程式的使用者)。

因此,SQL Connect 提供開發環境和工具,讓您為伺服器部署的結構定義、查詢和變異建立原型。此外,在您設計原型時,系統也會自動產生用戶端 SDK。

反覆更新服務和用戶端應用程式後,伺服器端和用戶端更新都已準備就緒,可以部署。

用戶端開發工作流程為何?

如果您已按照「入門指南」操作,應該已瞭解 SQL Connect 的整體開發流程。本指南將詳細說明如何從結構定義產生 Web SDK,以及如何使用用戶端查詢和變異。

總結來說,如要在用戶端應用程式中使用產生的 Web SDK,請按照下列必要步驟操作:

  1. 將 Firebase 新增至網頁應用程式。

接著:

  1. 開發應用程式結構定義。
  2. 使用 JavaScript SDK 初始化用戶端程式碼。
  3. 設定 SDK 產生作業:
    • 使用 SQL Connect VS Code 擴充功能中的「Add SDK to app」按鈕。
    • 更新 JavaScript SDK 的 connector.yaml。
  4. 使用 JavaScript SDK 匯入程式庫和產生的程式碼。
  5. 使用 JavaScript SDK 實作查詢和變動呼叫。
  6. 使用 JavaScript SDK 設定 SQL Connect 模擬器,進行測試。

使用 Firebase JavaScript SDK 導入用戶端程式碼

本節說明如何使用 Firebase JavaScript SDK 導入用戶端。

如果您使用 React 或 Angular,請參閱其他設定操作說明,以及為架構產生 SQL Connect SDK 的其他說明文件連結。

初始化應用程式

首先,請使用標準 Firebase 序列初始化應用程式。

initializeApp({...});

安裝產生的 JavaScript SDK

使用 Firebase CLI 在應用程式中設定 SQL Connect 生成的 SDK。init 指令應會偵測目前資料夾中的所有應用程式,並自動安裝產生的 SDK。

firebase init dataconnect:sdk

將應用程式連結至 SQL Connect 服務。

import { connectDataConnectEmulator } from 'firebase/data-connect';
import { connectorConfig } from '@dataconnect/generated';

const dataConnect = getDataConnect(connectorConfig);
// [Optionally] Configure the SDK to use Data Connect local emulator.
connectDataConnectEmulator(dataConnect, 'localhost', 9399);

在原型設計階段更新 SDK

如果已安裝 SQL Connect VS Code 擴充功能,系統會隨時更新產生的 SDK。

如果您不使用 SQL Connect VS Code 擴充功能,可以使用 Firebase CLI,讓產生的 SDK 保持最新狀態。

firebase dataconnect:sdk:generate --watch

在建構管道中產生 SDK

您可以使用 Firebase CLI,在 CI/CD 建構程序中生成 SQL Connect SDK。

firebase dataconnect:sdk:generate

匯入程式庫

初始化用戶端程式碼時,需要匯入兩組項目:一般 SQL Connect 匯入項目,以及產生的特定 SDK 匯入項目。

請注意一般匯入項目中包含的 ConnectorConfig 物件。

// general imports
import { ConnectorConfig, DataConnect, getDataConnect, QueryRef, MutationRef, QueryPromise, MutationPromise } from 'firebase/data-connect';

// generated queries and mutations from SDK
import { listMovies, ListMoviesResponse, createMovie, connectorConfig } from '@dataconnect/generated';

使用 JavaScript SDK 的查詢

產生的程式碼會預先定義查詢參照。您只需要匯入並呼叫執行即可。

import { executeQuery } from 'firebase/data-connect';
import { listMoviesRef } from '@dataconnect/generated';

const ref = listMoviesRef();
const { data } = await executeQuery(ref);
console.log(data.movies);

呼叫 SDK 查詢方法

以下是使用這些動作快速鍵函式的範例:

import { listMovies } from '@dataconnect/generated';
function onBtnClick() {
// This will call the generated JS from the CLI and then make an HTTP request out
// to the server.
  listMovies().then(data => showInUI(data)); // == executeQuery(listMoviesRef);
}

訂閱異動通知

請參閱「取得 SQL Connect 的即時更新」。

處理列舉欄位的變更

應用程式的結構定義可以包含列舉,並可透過 GraphQL 查詢存取。

隨著應用程式設計變更,您可能會新增列舉支援的值。舉例來說,假設您在應用程式生命週期的後續階段,決定在 AspectRatio 列舉中加入 FULLSCREEN 值。

在 SQL Connect 工作流程中,您可以使用本機開發人員工具更新查詢和 SDK。

不過,在您發布更新版用戶端之前,舊版部署的用戶端可能會中斷。

彈性導入範例

請務必在列舉值上,為 switch 陳述式新增 default 分支,或為與列舉值比較的 if/else if 區塊新增 else 分支。JavaScript/TypeScript 語言不會強制執行這項操作,但如果新增列舉值,這是讓用戶端程式碼保持穩健的方法。

const queryResult = await getOldestMovie();

if (queryResult.data) {
  // we can use a switch statement's "default" case to check for unexpected values
  const oldestMovieAspectRatio = queryResult.data.originalAspectRatio;
  switch (oldestMovieAspectRatio) {
      case AspectRatio.ACADEMY:
      case AspectRatio.WIDESCREEN:
      case AspectRatio.ANAMORPHIC:
        console.log('This movie was filmed in Academy, widescreen or anamorphic aspect ratio!');
        break;
      default:
        // the default case will catch FULLSCREEN, UNAVAILABLE or _UNKNOWN
        // it will also catch unexpected values the SDK isn't aware of, such as CINEMASCOPE
        console.log('This movie was was NOT filmed in Academy, widescreen or anamorphic.');
        break;
  }

  // alternatively, we can check to see if the returned enum value is a known value
  if (!Object.values(AspectRatio).includes(oldestMovieAspectRatio)) {
    console.log(`Unrecognized aspect ratio: ${oldestAspectRatio}`);
  }
} else {
  console.log("no movies found!");
}

使用 JavaScript SDK 的異動

變動的存取方式與查詢相同。

import { executeMutation } from 'firebase/data-connect';
import { createMovieRef } from '@dataconnect/generated';

const { data } = await executeMutation(createMovieRef({ movie: 'Empire Strikes Back' }));

連線至 SQL Connect 模擬器

您也可以呼叫 connectDataConnectEmulator,然後傳入 SQL Connect 例項,連線至模擬器,如下所示:

import { connectDataConnectEmulator } from 'firebase/data-connect';
import { connectorConfig } from '@dataconnect/generated';

const dataConnect = getDataConnect(connectorConfig);
connectDataConnectEmulator(dataConnect, 'localhost', 9399);`

// Make calls from your app

如要切換至實際工作環境資源,請將連線至模擬器的程式碼行註解排除。

啟用用戶端快取

SQL Connect 提供選用的用戶端快取功能,您可以編輯 connector.yaml 檔案來啟用這項功能。啟用這項功能後,產生的用戶端 SDK 會在本機快取查詢回應,減少應用程式發出的資料庫要求數量,並在網路中斷時,讓應用程式中依賴資料庫的部分繼續運作。

如要啟用用戶端快取,請在連接器設定中新增用戶端快取設定:

generate:
  javascriptSdk:
    outputDir: ../web/
    package: "@dataconnect/generated"
    clientCache:
      maxAge: 5s
      storage: memory

這項設定有兩個參數,皆為選用:

  • maxAge:快取回應的最長保留時間,超過這個時間,用戶端 SDK 就會擷取新值。範例:「0」、「30s」、「1h30m」。

    maxAge 的預設值為 0,表示系統會快取回應,但用戶端 SDK 一律會擷取最新值。只有在 CACHE_ONLY 指定為 executeQuery(),且 subscribe() 傳回初始結果時,系統才會使用快取值。

  • storage:用戶端 SDK 可設為將回應快取至 persistent 儲存空間或 memory。快取在 persistent 儲存空間中的結果,在應用程式重新啟動後仍會保留。網頁 SDK 僅支援 memory 儲存空間。

更新連接器的快取設定後,請重新產生用戶端 SDK 並重新建構應用程式。完成後,executeQuery() 和 subscribe() 會快取回應,並根據您設定的政策使用快取值。這通常會自動發生,您不需要採取任何額外步驟,但請注意下列事項:

  • executeQuery() 的預設行為如上所述:如果查詢結果已快取,且快取值不早於 maxAge,則使用快取值。這項預設行為稱為 PREFER_CACHE 政策。

    您也可以指定 executeQuery() 的個別叫用,只提供快取值 (CACHE_ONLY),或無條件從伺服器擷取最新值 (SERVER_ONLY)。

    await executeQuery(queryRef, QueryFetchPolicy.CACHE_ONLY);
    
    await executeQuery(queryRef, QueryFetchPolicy.SERVER_ONLY);
    
  • 呼叫 subscribe() 時,無論 maxAge 設定為何,系統一律會立即傳回快取內容 (如有)。後續對 executeQuery() 的呼叫會根據設定的 maxAge 通知事件監聽器。

SDK 中的資料類型

SQL Connect 伺服器代表常見的 GraphQL 資料類型。在 SDK 中,這些狀態的表示方式如下。

SQL Connect 類型 TypeScript
時間戳記 字串
日期 字串
UUID 字串
Int64 字串
雙人床 數字
浮點值 數字

使用 TanStack 產生 React 和 Angular SDK

Firebase SQL Connect 提供產生的 SDK,其中包含 React 和 Angular 的掛鉤,並使用合作夥伴 Invertase 提供的程式庫 TanStack Query Firebase。

這個程式庫提供一組掛鉤,可大幅簡化在應用程式中處理 Firebase 非同步工作的程序。

TanStack 內建用戶端快取和即時訂閱功能,可與 SQL Connect 的內建即時支援功能搭配使用,但難度較高。建議您使用以 TanStack 為基礎的繫結,或 SQL Connect 的內建即時支援,但不要同時使用兩者。

請注意,SQL Connect 自己的即時實作方式比 TanStack 繫結有一些優點:

  • 正規化快取:SQL Connect 實作正規化快取,與查詢層級快取相比,可提升資料一致性,以及記憶體和網路效率。使用正規化快取時,如果應用程式某個區域中的實體更新,使用該實體的其他區域也會更新。
  • 遠端撤銷:SQL Connect 可從遠端撤銷所有訂閱裝置上的快取實體。

初始化應用程式

首先,與任何 Firebase 網頁應用程式一樣,請使用標準 Firebase 序列初始化應用程式。

initializeApp({...});

安裝 TanStack Query Firebase 套件

在專案中安裝 TanStack Query 套件。

回應

npm i --save @tanstack/react-query @tanstack-query-firebase/react
npm i --save firebase@latest # Note: React has a peer dependency on ^11.3.0

Angular

ng add @angular/fire

生成 React 或 Angular SDK

如前文所述,Firebase 工具會根據您的結構定義和作業,自動產生 SDK,與標準網頁 SDK 相同。

如果您剛將 React 或 Angular 新增至專案,請重新執行 firebase init dataconnect:sdk,重新設定產生的 SDK,加入額外的框架繫結。

匯入程式庫

您需要匯入四組項目,才能初始化 React 或 Angular 用戶端程式碼:一般 SQL Connect 匯入項目、一般 TanStack 匯入項目,以及 JS 和 React 生成 SDK 的特定匯入項目。

請注意一般匯入項目中包含的 ConnectorConfig 類型。

回應

// general imports
import { ConnectorConfig, DataConnect, getDataConnect, QueryRef, MutationRef, QueryPromise, MutationPromise } from 'firebase/data-connect';

// TanStack Query-related functions
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

// generated queries and mutations from SDK
import { ListMoviesResponse, connectorConfig } from '@dataconnect/generated';

// generated React hooks from SDK
import { useListAllMovies, useCreateMovie } from "@dataconnect/generated/react";

Angular

// general imports
import { ConnectorConfig, DataConnect, getDataConnect, QueryRef, MutationRef, QueryPromise, MutationPromise } from 'firebase/data-connect';

// TanStack Query-related functions
import { provideTanStackQuery, QueryClient } from "@tanstack/angular-query-experimental";

// generated queries and mutations from SDK
import { ListMoviesResponse, connectorConfig } from '@dataconnect/generated';

// generated React hooks from SDK
import { injectListAllMovies, injectCreateMovie } from "@dataconnect/generated/angular";

在 React 或 Angular 用戶端中使用查詢和變異

設定完成後,您就可以納入產生的 SDK 方法。

在下列程式碼片段中,請注意 React 的 use 前置字元方法 useListAllMovies 和 Angular 的 inject 前置字元方法 injectListAllMovies,兩者都來自產生的 SDK。

回應

產生的 SDK 中,所有這類作業 (包括查詢和異動) 都會呼叫 TanStackQuery 繫結:

import { useListAllMovies } from '@dataconnect/generated/react';

function MyComponent() {
  const { isLoading, data, error } = useListAllMovies();
  if(isLoading) {
    return <div>Loading...</div>
  }
  if(error) {
    return <div> An Error Occurred: {error} </div>
  }
}

// App.tsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import MyComponent from './my-component';

function App() {
  const queryClient = new QueryClient();
  return <QueryClientProvider client={queryClient}>
    <MyComponent />
  </QueryClientProvider>
}

Angular

import { injectAllMovies, connectorConfig } from '@dataconnect/generated/angular';
import { provideDataConnect, getDataConnect } from '@angular/fire/data-connect';
import { provideTanStackQuery, QueryClient } from "@tanstack/angular-query-experimental";
const queryClient = new QueryClient();
...
providers: [
  ...
  provideTanStackQuery(queryClient),
  provideDataConnect(() => {
    const dc = getDataConnect(connectorConfig);
    return dc;
  })
]

搭配使用自動重新載入查詢與 React 和 Angular

您可以設定查詢,在資料變更時自動重新載入。

回應

export class MovieListComponent {
  movies = useListAllMovies();
}

export class AddPostComponent {
  const mutation = useCreateMovie({ invalidate: [listAllMoviesRef()] });
  addMovie() {
    // The following will automatically cause TanStack to reload its listAllMovies query
    mutation.mutate({ title: 'The Matrix });
  }
}

Angular

// class
export class MovieListComponent {
  movies = injectListAllMovies();
}

// template
@if (movies.isPending()) {
    Loading...
}
@if (movies.error()) {
    An error has occurred: {{  movies.error() }}
}
@if (movies.data(); as data) {
    @for (movie of data.movies; track movie.id) {
    <mat-card appearance="outlined">
        <mat-card-content>{{movie.description}}</mat-card-content>
    </mat-card>
    } @empty {
        <h2>No items!</h2>
    }
}

連線至 SQL Connect 模擬器

您也可以選擇呼叫 connectDataConnectEmulator,然後將 SQL Connect 例項傳遞至產生的掛鉤,藉此連線至模擬器,如下所示:

React

import { getDataConnect, connectDataConnectEmulator } from 'firebase/data-connect';
import { connectorConfig } from '@dataconnect/generated';
import { useListAllMovies } from '@dataconnect/generated/react';

const dc = getDataConnect(connectorConfig);
connectDataConnectEmulator(dc, 'localhost', 9399);

class AppComponent() {
  ...
  const { isLoading, data, error } = useListAllMovies(dc);
  ...
}

Angular

// app.config.ts
import { provideDataConnect } from '@angular/fire/data-connect';
import { getDataConnect, connectDataConnectEmulator } from 'firebase/data-connect';
provideDataConnect(() => {
  const dc = getDataConnect(connectorConfig);
  connectDataConnectEmulator(dc, 'localhost', 9399);
  return dc;
}),

如要切換至實際工作環境資源,請將連線至模擬器的程式碼行註解排除。

在原型設計階段更新 SDK

如果已安裝 SQL Connect VS Code 擴充功能,系統會隨時更新產生的 SDK。

如果您不使用 SQL Connect VS Code 擴充功能,可以使用 Firebase CLI,讓產生的 SDK 保持最新狀態。

firebase dataconnect:sdk:generate --watch

在建構管道中產生 SDK

您可以使用 Firebase CLI,在 CI/CD 建構程序中生成 SQL Connect SDK。

firebase dataconnect:sdk:generate