使用生成的 Web SDK

借助 Firebase Data Connect 客户端 SDK,您可以直接从 Firebase 应用调用服务器端查询和突变。在设计部署到 Data Connect 服务的架构、查询和突变时,您可以并行生成自定义客户端 SDK。然后,将此 SDK 中的方法集成到您的客户端逻辑中。

正如我们在其他地方提到的,请务必注意,Data Connect查询和突变不是由客户端代码提交的,而是在服务器上执行的。相反,部署后,Data Connect 操作会像 Cloud Functions 一样存储在服务器上。这意味着您需要部署相应的客户端更改,以避免影响现有用户(例如,使用旧版应用的用户)。

因此,Data Connect 为您提供了一个开发者环境和工具,让您可以对服务器部署的架构、查询和突变进行原型设计。它还会在您进行原型设计时自动生成客户端 SDK。

当您对服务和客户端应用进行迭代更新后,服务器端和客户端更新即可部署。

客户端开发工作流程是怎样的?

如果您按照使用入门中的说明操作,则已了解 Data Connect 的整体开发流程。在本指南中,您可以详细了解如何从架构生成 Web SDK,以及如何处理客户端查询和变更。

总而言之,如需在客户端应用中使用生成的 Web SDK,您需要先完成以下前提步骤:

  1. 将 Firebase 添加到您的网页应用。

然后:

  1. 开发应用架构。
  2. 使用 JavaScript SDKReact/Angular 库初始化客户端代码。
  3. 对于 React 和 Angular,安装 Tanstack Query 软件包
  4. 设置 SDK 生成:

    • 使用 Data Connect VS Code 扩展程序中的将 SDK 添加到应用按钮
    • 通过更新 JavaScript SDKReactAngularconnector.yaml
  5. 使用 JavaScript SDKReactAngular 导入库和生成的代码。

  6. 使用 JavaScript SDKReact/Angular 实现对查询和突变的调用。

  7. 通过使用 JavaScript SDKReact/Angular 设置 Data Connect 模拟器进行测试。

使用 Firebase JavaScript SDK 实现客户端代码

本部分介绍了如何使用 Firebase JavaScript SDK 实现客户端。

如果您使用的是 React 或 Angular,请参阅有关为框架生成 Data Connect SDK 的替代设置说明和指向其他文档的链接。

初始化您的应用

首先,使用标准 Firebase 序列初始化您的应用。

initializeApp({...});

生成 JavaScript SDK

与大多数 Firebase 项目一样,Firebase Data Connect客户端Firebase Data Connect代码的开发工作在本地项目目录中进行。Data Connect VS Code 扩展程序和 Firebase CLI 都是用于生成和管理客户端代码的重要本地工具。

SDK 生成选项与您初始化项目时生成的 dataconnect.yaml 文件中的多个条目相关联。

初始化 SDK 生成

connector.yaml 中,添加 outputDirpackage 和(对于 Web SDK)packageJsonDir
generate:
  javascriptSdk:
    outputDir: "../movies-generated"
    package: "@movie-app/movies"
    packageJsonDir: "../../"

outputDir 用于指定生成的 SDK 应输出到何处。

package 指定软件包名称。

packageJsonDir 指定软件包的安装位置。

在这种情况下,请安装 firebase@latest 以确保满足此对等依赖项。

初始化 JavaScript SDK

使用您在设置 Data Connect 时所用的信息(全部可在 Firebase 控制台的“Data Connect”标签页中找到)初始化 Data Connect 实例。

ConnectorConfig 对象

SDK 需要连接器配置对象。

此对象是根据 dataconnect.yaml 中的 serviceIdlocation 以及 connector.yaml 中的 connectorId 自动生成的。

导入库

初始化客户端代码需要两组导入:常规 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 '@myorg/myconnector';

使用 JavaScript SDK 中的查询

生成的代码将已包含预定义的查询引用。您只需导入这些模型并对其调用 execute。

import { executeQuery } from 'firebase/data-connect';
import { listMoviesRef } from '@movie-app/movies';

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

调用 SDK 查询方法

以下示例使用了这些操作快捷方式函数:

import { listMovies } from '@movie-app/movies';
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`

使用 JavaScript SDK 中的突变

突变的访问方式与查询相同。

import { executeMutation } from 'firebase/data-connect';
import { createMovieRef } from '@movie-app/movies';

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

连接到 Data Connect 模拟器

(可选)您可以通过调用 connectDataConnectEmulator 并传入 Data Connect 实例来连接到模拟器,如下所示:

import { connectDataConnectEmulator } from 'firebase/data-connect';
import { connectorConfig } from '@myorg/myconnector'; // Replace with your package name

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

// Make calls from your app

如需切换到生产资源,请注释掉用于连接到模拟器的行。

为 React 和 Angular 实现客户端代码

Firebase Data Connect 提供了一个生成的 SDK,其中包含使用 Invertase 合作伙伴提供的库(即 TanStack Query Firebase)的 React 和 Angular 钩子。

此库提供了一组钩子,可大大简化在应用中使用 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 SDK,请向 connector.yaml 配置文件添加 react 键。

回应

generate:
  javascriptSdk:
    react: true
    outputDir: "../movies-generated"
    package: "@movie-app/movies"
    packageJsonDir: "../../"

Angular

generate:
  javascriptSdk:
    angular: true
    outputDir: "../movies-generated"
    package: "@movie-app/movies"
    packageJsonDir: "../../"

导入库

您需要四组导入才能初始化 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 '@myorg/myconnector';

// generated React hooks from SDK
import { useListAllMovies, useCreateMovie } from "@myorg/connector/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 '@myorg/myconnector';

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

在 React 或 Angular 客户端中使用查询和 mutation

设置完成后,您就可以使用生成的 SDK 中的方法了。

在以下代码段中,请注意以 use 为前缀的 React 方法 useListAllMovies 和以 inject 为前缀的 Angular 方法 injectListAllMovies,这两个方法均来自生成的 SDK。

回应

生成的 SDK 中的所有此类操作(包括查询和 mutation)都会调用 TanStackQuery 绑定:

import { useListAllMovies } from '@movies-app/movies/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 '@movies-app/movies/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 '@movies-app/movies';
import { useListAllMovies } from '@movies-app/movies/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 生成的特殊注意事项

配置相对于 node_modules 的路径

对于 JavaScript SDK,由于 Data Connect 使用 npm link 安装您的 SDK,因此生成的 SDK 需要输出到与 node_modules 路径处于同一级别的目录或可访问 node_modules 的子目录中。

换句话说,生成的 SDK 需要有权访问 firebase 节点模块才能正常运行。

例如,如果您的 node_modules 位于 my-app/ 中,则输出目录应为 my-app/js-email-generated,以便 js-email-generated 可以从其父级 node_modules 文件夹导入。

my-app/
  dataconnect/
    connector/
        connector.yaml
  node_modules/
    firebase/
  js-email-generated/
// connector.yaml
connectorId: "my-connector"
generate:
  javascriptSdk:
    outputDir: "../../js-email-generated"
    package: "@myapp/my-connector"

或者,如果您有一个模块托管在根目录中的单体代码库,则可以将输出目录放在单体代码库中的任何文件夹中。

my-monorepo/
  dataconnect/
    connector/
        connector.yaml
  node_modules/
    firebase/
  my-app/
    js-email-generated/
  package.json
// connector.yaml
connectorId: "my-connector"
generate:
  javascriptSdk:
    outputDir: "../../my-app/js-email-generated" # You can also output to ../../js-email-generated

在原型设计期间更新 SDK

如果您使用 Data Connect VS Code 扩展程序及其 Data Connect 模拟器进行交互式原型设计,那么在您修改定义架构、查询和变更的 .gql 文件时,系统会自动生成并更新 SDK 源文件。在热(重新)加载工作流中,这可能是一项实用功能。

在其他情况下,如果您使用的是 Firebase CLI 中的 Data Connect 模拟器,则可以监视 .gql 更新,还可以自动更新 SDK 来源。

或者,您也可以使用 CLI 在每次更改 .gql 文件时重新生成 SDK:

firebase dataconnect:sdk:generate --watch

生成用于集成和正式版发布的 SDK

在某些情况下(例如准备要提交以进行 CI 测试的项目源),您可以调用 Firebase CLI 进行批量更新。

在这些情况下,请使用 firebase dataconnect:sdk:generate