嵌入式分析SDK - 将SDK与Next.js结合使用
关于将嵌入式分析SDK与Next.js结合使用的一些注意事项。SDK经过测试可与Next.js 14配合使用,但可能也适用于其他版本。
带有服务器端渲染(SSR)或React服务器组件的SDK组件
目前,SDK组件仅支持客户端渲染。要将SDK组件与服务器端渲染或React服务器组件结合使用,您可以选择使用兼容层或手动包装组件。
服务器端渲染(SSR)的兼容层(实验性)
为了在Next.js中使用SDK组件,SDK提供了一个实验性兼容层,它使用动态导入包装所有组件并禁用SSR。为了与应用程序路由配合使用,此兼容层使用了use client
。
要使用兼容层,请将您的导入从@metabase/embedding-sdk-react
更改为@metabase/embedding-sdk-react/nextjs
。
手动包装组件
如果您想自定义组件的加载,可以创建自己的包装器。
在您的应用程序中,创建一个名为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
指令,并将导出一个禁用SSR的延迟加载版本的EmbeddingSdkProvider
。
"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 的文档。