借助 Firebase Data Connect 客户端 SDK,您可以直接从 Firebase 应用调用服务器端查询和突变。在设计部署到 Data Connect 服务的架构、查询和突变时,您可以并行生成自定义客户端 SDK。然后,将此 SDK 中的方法集成到您的客户端逻辑中。
正如我们在其他地方提到的,请务必注意,Data Connect查询和变更不是由客户端代码提交的,而是在服务器上执行的。相反,在部署时,Data Connect 操作会像 Cloud Functions 一样存储在服务器上。这意味着您需要部署相应的客户端更改,以避免影响现有用户(例如,使用旧版应用的用户)。
因此,Data Connect 为您提供了一个开发者环境和工具,让您可以设计服务器部署的架构、查询和突变原型。它还会在您进行原型设计时自动生成客户端 SDK。
当您对服务和客户端应用进行迭代更新后,服务器端和客户端更新即可部署。
客户端开发工作流程是什么?
如果您按照使用入门中的说明操作,则已了解 Data Connect 的整体开发流程。在本指南中,您可以详细了解如何从架构生成 Web SDK,以及如何处理客户端查询和变更。
总而言之,如需在客户端应用中使用生成的 Web SDK,您需要先完成以下前提条件步骤:
- 将 Firebase 添加到您的网页应用。
然后:
- 开发应用架构。
- 使用 JavaScript SDK 或 React/Angular 库初始化客户端代码。
- 对于 React 和 Angular,安装 Tanstack Query 软件包
- 设置 SDK 生成: - 借助 Data Connect VS Code 扩展程序中的将 SDK 添加到应用按钮
- 通过更新 JavaScript SDK、React 或 Angular 的 connector.yaml。
 
- 使用 JavaScript SDK 或 React 或 Angular 导入库和生成的代码。 
- 使用 JavaScript SDK 或 React/Angular 实现对查询和突变的调用。 
- 通过使用 JavaScript SDK 或 React/Angular 设置 Data Connect 模拟器来进行测试。 
使用 Firebase JavaScript SDK 实现客户端代码
本部分介绍了如何使用 Firebase JavaScript SDK 实现客户端。
如果您使用的是 React 或 Angular,请参阅有关为框架生成 Data Connect SDK 的替代设置说明和指向其他文档的链接。
初始化您的应用
首先,使用标准 Firebase 序列初始化您的应用。
initializeApp({...});
安装生成的 JavaScript SDK
使用 Firebase CLI 在应用中设置生成的 Data Connect SDK。
init 命令应检测当前文件夹中的所有应用,并自动安装生成的 SDK。
firebase init dataconnect:sdk
将您的应用连接到 Data 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
如果您安装了 Data Connect VS Code 扩展程序,该扩展程序将始终保持生成的 SDK 为最新状态。
如果您不使用 Data Connect VS Code 扩展程序,可以使用 Firebase CLI 来确保生成的 SDK 保持最新状态。
firebase dataconnect:sdk:generate --watch在构建流水线中生成 SDK
您可以在 CI/CD 构建流程中使用 Firebase CLI 生成 Data Connect SDK。
firebase dataconnect:sdk:generate导入库
初始化客户端代码需要两组导入:常规 Data 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 中的查询
生成的代码将已包含预定义的查询引用。您只需导入并调用它们的 execute 方法即可。
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);
}
订阅更改
您可以订阅更改(这样,每次执行查询时都会进行更新)。
const listRef = listAllMoviesRef();
// subscribe will immediately invoke the query if no execute was called on it previously.
subscribe(listRef, ({ data }) => {
 updateUIWithMovies(data.movies);
});
await createMovie({ title: 'Empire Strikes Back', releaseYear: 1980, genre: "Sci-Fi", rating: 5 });\
await listMovies(); // will update the subscription above`
处理对枚举字段的更改
应用的架构可以包含枚举,这些枚举可供 GraphQL 查询访问。
随着应用设计发生变化,您可能会添加新的枚举支持值。例如,假设在应用的生命周期后期,您决定向 AspectRatio 枚举添加 FULLSCREEN 值。
在 Data 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' }));
连接到 Data Connect 模拟器
(可选)您可以通过调用 connectDataConnectEmulator 并传入 Data 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
如需切换到生产资源,请注释掉用于连接到模拟器的行。
为 React 和 Angular 实现客户端代码
Firebase Data Connect 提供了一个生成的 SDK,其中包含用于 React 和 Angular 的钩子,这些钩子使用 Invertase 合作伙伴提供的库,即 TanStack Query Firebase。
此库提供了一组钩子,可大大简化在应用中使用 Firebase 处理异步任务的操作。
初始化您的应用
首先,与任何 Firebase Web 应用一样,使用标准 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
与标准 Web SDK 一样(如前文所述),Firebase 工具会根据您的架构和操作自动生成 SDK。
如果您刚刚向项目添加了 React 或 Angular,请重新运行 firebase init dataconnect:sdk 以重新配置生成的 SDK,使其包含额外的框架绑定。
导入库
您需要四组导入才能初始化 React 或 Angular 客户端代码:常规 Data 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 中的方法了。
在以下代码段中,请注意以 use 为前缀的 React 方法 useListAllMovies 和以 inject 为前缀的 Angular 方法 injectListAllMovies,它们都来自生成的 SDK。
回应
生成的 SDK 中的所有此类操作(包括查询和变异)都会调用 TanStackQuery 绑定:
- 查询调用并返回 TanStack useDataConnectQueryhook
- mutation 调用并返回 TanStack useDataConnectMutationhook
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>
    }
}
连接到 Data Connect 模拟器
(可选)您可以通过调用 connectDataConnectEmulator 连接到模拟器,然后将 Data 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 中的数据类型
Data Connect 服务器表示常见的 GraphQL 数据类型。在 SDK 中,这些参数表示如下。
| 数据连接类型 | TypeScript | 
|---|---|
| 时间戳 | 字符串 | 
| 日期 | 字符串 | 
| UUID | 字符串 | 
| Int64 | 字符串 | 
| 双精度型 | 数字 | 
| 浮点数 | 数字 | 
在原型设计期间更新 SDK
如果您安装了 Data Connect VS Code 扩展程序,该扩展程序将始终保持生成的 SDK 为最新状态。
如果您不使用 Data Connect VS Code 扩展程序,可以使用 Firebase CLI 来确保生成的 SDK 保持最新状态。
firebase dataconnect:sdk:generate --watch在构建流水线中生成 SDK
您可以在 CI/CD 构建流程中使用 Firebase CLI 生成 Data Connect SDK。
firebase dataconnect:sdk:generate