嵌入式分析 SDK - 将 SDK 与 Next.js 结合使用

嵌入式分析 SDK 仅适用于 ProEnterprise 计划(包括自托管和 Metabase 云版)。但是,您可以通过使用 API 密钥进行嵌入式身份验证,在本地机器上无需许可证即可试用 SDK。

关于将嵌入式分析 SDK 与 Next.js 结合使用的一些注意事项。SDK 已经过测试,可与 Next.js 14 配合使用,尽管它可能也适用于其他版本。

带服务器端渲染 (SSR) 或 React 服务器组件的 SDK 组件

目前,SDK 组件仅支持客户端渲染。要在服务器端渲染或 React 服务器组件中使用 SDK 组件,您可以使用兼容层或手动封装组件。

服务器端渲染 (SSR) 兼容层(实验性)

要在 Next.js 中使用 SDK 组件,SDK 提供了一个实验性兼容层,它 用动态导入封装了所有组件并禁用了 SSR。为了与应用程序路由兼容,此兼容层使用了 use client

要使用兼容层,请将您的导入从 @metabase/embedding-sdk-react 更改为 @metabase/embedding-sdk-react/nextjs

请参阅 使用此兼容层的 Next.js 示例应用

手动封装组件

如果您想自定义组件的加载,可以创建自己的封装。

在您的应用程序中,创建一个 metabase 目录,并在该目录中添加一个 EmbeddingSdkProvider.tsx 文件。此文件将包含具有适当配置的提供程序。

"use client";

import {
  MetabaseProvider,
  defineMetabaseAuthConfig,
} from "@metabase/embedding-sdk-react";

const authConfig = defineMetabaseAuthConfig({
  metabaseInstanceUrl: process.env.NEXT_PUBLIC_METABASE_INSTANCE_URL,
});

export const EmbeddingSdkProvider = ({
  children,
}: {
  children: React.ReactNode;
}) => {
  return (
    <MetabaseProvider authConfig={authConfig}>{children}</MetabaseProvider>
  );
};

接下来,在该 metabase 目录中添加一个 index.tsx 文件。此文件将包含 use client 指令,并将导出 EmbeddingSdkProvider 的延迟加载版本,并禁用 SSR。

"use client";

import dynamic from "next/dynamic";

import type React from "react";

// Lazy load the EmbeddingSdkProvider so and let it render children while it's being loaded
export const EmbeddingSdkProviderLazy = ({
  children,
}: {
  children: React.ReactNode;
}) => {
  const EmbeddingSdkProvider = dynamic(
    () =>
      import("./EmbeddingSdkProvider").then(m => {
        return { default: m.EmbeddingSdkProvider };
      }),
    {
      ssr: false,
      loading: () => {
        // render children while loading
        return <div>{children}</div>;
      },
    },
  );

  return <EmbeddingSdkProvider>{children}</EmbeddingSdkProvider>;
};

// Wrap all components that you need like this:

export const StaticQuestion = dynamic(
  () => import("@metabase/embedding-sdk-react").then(m => m.StaticQuestion),
  {
    ssr: false,
    loading: () => {
      return <div>Loading...</div>;
    },
  },
);

export const StaticDashboard = dynamic(
  () => import("@metabase/embedding-sdk-react").then(m => m.StaticDashboard),
  {
    ssr: false,
    loading: () => {
      return <div>Loading...</div>;
    },
  },
);

您现在可以像这样导入组件:

import { StaticQuestion } from "@/metabase"; // path to the folder created earlier

export default function Home() {
  return <StaticQuestion questionId={123} />;
}

处理身份验证

App Router 和 Pages Router 有不同的 API 路由定义方式。如果您想通过 JWT 从服务器对用户进行身份验证,可以按照以下说明操作。但如果您想在本地开发中使用 API 密钥进行身份验证,请参阅使用 API 密钥进行本地身份验证

使用 App Router

您可以创建一个路由处理程序,用于将用户登录到 Metabase。

在您的 app/* 目录中创建一个新的 route.ts 文件,例如 app/sso/metabase/route.ts,它对应于 /sso/metabase 上的一个端点。此路由处理程序应为经过身份验证的用户生成 JWT,并以 { jwt: string } 的 JSON 对象形式返回该令牌。

import jwt from "jsonwebtoken";

const METABASE_JWT_SHARED_SECRET = process.env.METABASE_JWT_SHARED_SECRET || "";
const METABASE_INSTANCE_URL = process.env.METABASE_INSTANCE_URL || "";

export async function GET() {
  const token = jwt.sign(
    {
      email: user.email,
      first_name: user.firstName,
      last_name: user.lastName,
      groups: [user.group],
      exp: Math.round(Date.now() / 1000) + 60 * 10, // 10 minutes expiration
    },
    // This is the JWT signing secret in your Metabase JWT authentication setting
    METABASE_JWT_SHARED_SECRET,
  );
  // The user backend should return a JSON object with the JWT.
  return Response.json({ jwt: token });
}

然后,将此 authConfig 传递给 MetabaseProvider

import { defineMetabaseAuthConfig } from "@metabase/embedding-sdk-react/nextjs";

const authConfig = defineMetabaseAuthConfig({
  metabaseInstanceUrl: "https://metabase.example.com", // Required: Your Metabase instance URL
});

使用 Pages Router

您可以创建一个 API 路由,用于将用户登录到 Metabase。

在您的 pages/api/* 目录中创建一个新的 metabase.ts 文件,例如 pages/api/sso/metabase.ts,它对应于 /api/sso/metabase 上的一个端点。此 API 路由应为经过身份验证的用户生成 JWT,并以 { jwt: string } 的 JSON 对象形式返回该令牌。

import type { NextApiRequest, NextApiResponse } from "next";
import jwt from "jsonwebtoken";

const METABASE_JWT_SHARED_SECRET = process.env.METABASE_JWT_SHARED_SECRET || "";
const METABASE_INSTANCE_URL = process.env.METABASE_INSTANCE_URL || "";

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse,
) {
  const token = jwt.sign(
    {
      email: user.email,
      first_name: user.firstName,
      last_name: user.lastName,
      groups: [user.group],
      exp: Math.round(Date.now() / 1000) + 60 * 10, // 10 minutes expiration
    },
    // This is the JWT signing secret in your Metabase JWT authentication setting
    METABASE_JWT_SHARED_SECRET,
  );
  // The user backend should return a JSON object with the JWT.
  res.status(200).json({ jwt: token });
}

然后,将此 authConfig 传递给 MetabaseProvider

import { defineMetabaseAuthConfig } from "@metabase/embedding-sdk-react/nextjs";

const authConfig = defineMetabaseAuthConfig({
  metabaseInstanceUrl: "https://metabase.example.com", // Required: Your Metabase instance URL
});

阅读其他 Metabase 版本的文档。

© . All rights reserved.