生成されたウェブ 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 SDKReact、または Angular を使用して、ライブラリと生成されたコードをインポートします。

  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 クライアント コードの作業はローカル プロジェクト ディレクトリで行います。Data Connect VS Code 拡張機能と Firebase CLI はどちらも、クライアント コードの生成と管理に重要なローカル ツールです。

SDK 生成オプションは、プロジェクトの初期化時に生成された dataconnect.yaml ファイル内の複数のエントリにキーされています。

SDK 生成を初期化する

connector.yamloutputDirpackage、(ウェブ SDK の場合は)packageJsonDir を追加します。
generate:
  javascriptSdk:
    outputDir: "../movies-generated"
    package: "@movie-app/movies"
    packageJsonDir: "../../"

outputDir には、生成された SDK の出力先を指定します。

package にはパッケージ名を指定します。

packageJsonDir は、パッケージをインストールする場所を指定します。

この場合は、firebase@latest をインストールして、このピア依存関係が確実に満たされるようにします。

JavaScript SDK を初期化する

Data Connect の設定に使用した情報を使用して Data Connect インスタンスを初期化します(すべて Firebase コンソールの [Data Connect] タブで確認できます)。

ConnectorConfig オブジェクト

SDK にはコネクタ構成オブジェクトが必要です。

このオブジェクトは、dataconnect.yamlserviceIdlocationconnector.yamlconnectorId から自動的に生成されます。

ライブラリをインポートする

クライアント コードを初期化するには、一般的な Data Connect インポートと、生成された特定の SDK インポートの 2 つのインポート セットが必要です。

一般的なインポートに含まれる 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 は、Google のパートナーである Invertase の TanStack Query Firebase で利用可能なライブラリを使用して、React と Angular 用のフックが生成された SDK を提供します。

このライブラリには、アプリで Firebase を使用して非同期タスクを簡単に処理できる一連のフックが用意されています。

アプリを初期化する

まず、他の Firebase ウェブアプリと同様に、標準の Firebase シーケンスを使用してアプリを初期化します。

initializeApp({...});

TanStack Query Firebase パッケージをインストールする

プロジェクトに TanStack Query のパッケージをインストールします。

ReactAngular
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
ng add @angular/fire

React または Angular SDK を生成する

前述のとおり、標準のウェブ SDK と同様に、Firebase ツールはスキーマとオペレーションに基づいて SDK の自動生成を処理します。

プロジェクトの React SDK を生成するには、connector.yaml 構成ファイルに react キーを追加します。

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

ライブラリをインポートする

React または Angular のクライアントコードを初期化するには、4 つのインポート セットが必要です。一般的な Data Connect インポート、一般的な TanStack インポート、JS と React で生成された SDK の特定のインポートです。

一般的なインポートに含まれている ConnectorConfig 型に注意してください。

ReactAngular
// 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";
// 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 クライアントでクエリとミューテーションを使用する

設定が完了したら、生成された SDK のメソッドを組み込むことができます。

次のスニペットでは、生成された SDK の use 接頭辞のメソッド useListAllMovies(React 用)と inject 接頭辞のメソッド injectListAllMovies(Angular 用)に注目してください。

ReactAngular

生成された SDK のこのようなオペレーションはすべて、クエリとミューテーションの両方で 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>
}
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 で自動再読み込みクエリを使用する

データが変更されたときに自動的に再読み込みされるようにクエリを構成できます。

ReactAngular
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 });
  }
}
// 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 Angular
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);
  ...
}
// 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 で次のように表されます。

Data Connect の種類 TypeScript
タイムスタンプ 文字列
日付 文字列
UUID 文字列
Int64 文字列
Double 数値
浮動小数点数 数値

SDK 生成に関する特別な考慮事項

node_modules を基準とするパスを構成する

JavaScript SDK の場合、Data Connectnpm link を使用して SDK をインストールするため、生成された SDK は node_modules パスと同じレベルのディレクトリ、または node_modules にアクセスできる子ディレクトリに出力する必要があります。

つまり、生成された SDK が正しく機能するには、firebase ノード モジュールにアクセスできる必要があります。

たとえば、node_modulesmy-app/ にある場合、js-email-generated が親の node_modules フォルダからインポートできるように、出力ディレクトリは my-app/js-email-generated にする必要があります。

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"

モジュールがルートでホストされている monorepo がある場合は、出力ディレクトリを monorepo 内の任意のフォルダに配置できます。

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 を使用します。