Docs 菜单

Docs 主页开发应用程序Atlas Device SDKs

Next.js 集成指南 — Web SDK

在此页面上

  • 开始之前
  • 添加身份验证
  • 客户端渲染
  • 服务器端渲染
  • 静态渲染
  • 从 Next.js 查询 MongoDB 的替代方法

以下指南解释了如何将 Realm Web SDK 集成到 Next.js 应用程序。您可以使用 Realm Web SDK 从 Web 应用程序(例如使用 Next.js 开发的应用程序)访问 MongoDB Atlas 中的数据。 Realm Web SDK 通过 Atlas App Services 与 MongoDB Atlas 中的数据连接。 Next.js 是一个基于 React 的 Web 框架,用于处理应用程序配置和结构,并支持客户端、服务器端和静态呈现。

Realm Web SDK 支持 Next.js 中的所有渲染模式:

  • 客户端渲染:使用 Atlas GraphQL API 或 MongoDB 数据访问权限直接从浏览器查询 MongoDB。

  • 服务器端渲染:使用 App Services 通过浏览器对用户进行身份验证,使用服务器上的 GraphQL API 进行查询

  • 静态渲染:从 MondoDB Atlas 获取数据,从而在构建时生成页面。

使用本集成指南之前,您应该:

提示

MongoDB Atlas Vercel 集成

如果使用 Vercel 托管 Next.js 应用,请添加 MongoDB Atlas 集成以轻松将 Next.js 应用连接到 Atlas。

了解有关 Vercel MongoDB Atlas 集成的更多信息。

从应用查询 MongoDB 之前,您必须初始化 App Services 客户端并对用户进行身份验证。您可以按照以下步骤将 Realm Web SDK 连接到客户端 Next.js。

在此示例中,我们将在自定义 React Hook 中使用Realm.getApp()在整个应用程序中公开经过身份验证的 Realm.App实例。

提示

另请参阅:

有关在整个应用程序中公开 Realm 身份验证的其他方法,请参阅 Next.js 身份验证文档。

1

使用应用程序 ID 将 Next.js 应用程序连接到 Atlas App Services。通过以下操作,在整个应用程序中将应用程序 ID 作为环境变量公开:

  1. 查找应用程序 ID。

  2. 在项目的根目录中创建文件 .env.local

  3. 为 App ID 添加环境变量。要使 App ID 可以通过浏览器而不是服务器访问,请在其名称前面加上 NEXT_PUBLIC_

.env.local
NEXT_PUBLIC_APP_ID=<YOUR App Services App ID>
2

客户端使用 React Hook 实例化和访问Realm.App ,您可以使用该 Realm.App 通过 App ID 连接到 App Services。您将在本指南中创建的所有页面中使用此钩子。

  1. 创建文件 components/useApp.js

  2. 添加以下代码来实例化和访问 App 实例:

components/useApp.js
import { useEffect, useState } from "react";
import * as Realm from "realm-web";
export function useApp() {
const [app, setApp] = useState(null);
// Run in useEffect so that App is not created in server-side environment
useEffect(() => {
setApp(Realm.getApp(process.env.NEXT_PUBLIC_APP_ID));
}, []);
return app;
}
3

现在您可以使用 useApp() 钩子访问 app 实例,并用来登录用户。当用户访问应用程序主页时,在 pages/index.js 中进行匿名身份验证。

import { useEffect } from "react";
import * as Realm from "realm-web";
import Link from "next/link";
import { useApp } from "../components/useApp";
export default function Home() {
const app = useApp();
// note: useEffect runs in the browser but does not run during server-side rendering
useEffect(() => {
// If no logged in user, log in
if (app && !app.currentUser) {
const anonymousUser = Realm.Credentials.anonymous();
app.logIn(anonymousUser);
}
}, [app, app?.currentUser]);
return (
//Your app
);
}

在实际应用程序中,您需要更复杂的身份验证流程。有关更多信息,请参阅 Next.js 身份验证文档。

提示

本部分介绍如何将 Next.js 客户端呈现与 Realm Web SDK 集成。按照这些步骤,您可以在 Next.js 应用程序中通过客户端 JavaScript 直接查询 MongoDB 并与 Atlas App Services 无服务器后端交互。您可以使用MongoDB 数据访问Atlas GraphQL API 查询 MongoDB。

初始化 App 客户端并对用户进行身份验证后,可以使用 MongoDB 数据访问直接从应用程序中的客户端代码查询 MongoDB。

使用App.User.mongoClient()app对象访问 MongoDB 数据访问接口,然后用它来查询 MongoDB。

import { useEffect, useState } from "react";
import { useApp } from "../components/useApp";
function MongoDbDataAccess({ name }) {
const [plant, setPlant] = useState();
const app = useApp();
useEffect(() => {
if (app?.currentUser) {
const mongo = app?.currentUser?.mongoClient("mongodb-atlas");
const plants = mongo.db("example").collection("plants");
plants.findOne({ name }).then((foundPlant) => {
setPlant(foundPlant);
});
}
}, [app, app?.currentUser, app?.currentUser?.id, name]);
return (
<div>
<h1>Data from MongoDB Access</h1>
{plant ? (
<div>
<p>{plant.name}</p>
<p>{plant.color}</p>
</div>
) : (
"no plant"
)}
</div>
);
}
export default function DaffodilInformation() {
return <MongoDbDataAccess name="daffodil" />;
}

或者可以使用 Atlas GraphQL API 从 Next.js 客户端代码通过 GraphQL 查询 MongoDB。

此示例使用 Apollo GraphQL 客户端 执行 GraphQL 查询。安装 Apollo 客户端及其 npm 包 @apollo/client 及其对等依赖 graphql。

npm install @apollo/client graphql

现在您可以添加一个页面来执行 GraphQL 查询。页面中的代码会执行以下操作:

  1. 导入必要的依赖项

  2. 在提供商组件中创建 GraphQL 客户端。

  3. 定义该 GraphQL 查询。

  4. 创建组件,用于消耗 GraphQL 提供程序并运行查询。

  5. 导出包装消费者组件的提供者组件。

GraphQL 页面应如下所示:

// 1. Import dependencies
import {
ApolloClient,
ApolloProvider,
HttpLink,
InMemoryCache,
useQuery,
gql,
} from "@apollo/client";
import { useApp } from "../components/useApp";
// 2. Add GraphQL client provider
function GraphQLProvider({ children }) {
const app = useApp();
const client = new ApolloClient({
link: new HttpLink({
uri: process.env.NEXT_PUBLIC_GRAPHQL_API_ENDPOINT,
// We get the latest access token on each request
fetch: async (uri, options) => {
const accessToken = app.currentUser?.accessToken;
options.headers.Authorization = `Bearer ${accessToken}`;
return fetch(uri, options);
},
}),
cache: new InMemoryCache(),
});
return <ApolloProvider client={client}>{children}</ApolloProvider>;
}
// 3. GraphQL query
const GET_PLANT = gql`
query Plant($name: String!) {
plant(query: { name: $name }) {
_id
sunlight
name
color
type
_partition
}
}
`;
// 4. Consumer of provider and query
function PlantInformation({ name }) {
const { loading, error, data } = useQuery(GET_PLANT, {
variables: { name },
});
if (loading || !data) return <p>Loading ...</p>;
if (error) console.error("Failed with error:", error);
return (
<div>
{data.plant ? (
<div>
<p>{data.plant.name}</p>
<p>{data.plant.color}</p>
</div>
) : (
"no plant"
)}
</div>
);
}
// 5. Export page with the GraphQL query
export default function FullGraphQLPage() {
return (
<GraphQLProvider>
<PlantInformation name="daffodil" />
</GraphQLProvider>
);
}

提示

有关使用 GraphQL API 和 React 查询 Atlas 的更多信息,请参阅 Apollo 客户端(React)文档。

本部分介绍如何将 Next.js 服务器端呈现与 Realm Web SDK 集成。将 Realm Web SDK 与服务器端呈现结合使用,可让您以特定用户的身份访问数据。在此过程中,您可以将App Services 规则和权限应用于这些用户查询。

要直接从 Next.js 服务器查询 MongoDB Atlas,您必须设置两个不同的组件:Next.js 服务器上的 Atlas GraphQL API 和浏览器中的 Realm Web SDK。本部分介绍两者的设置。

您可能需要集成 Web SDK 和 Next.js,这样可以:

  • 在页面加载时直接访问存储在 Atlas 中的数据。

  • 对请求应用 Atlas App Services 规则和权限,以减少服务器端代码。

  • 减少客户端 JavaScript 的使用。

  • 执行服务器端数据操作。

从高层次来看,使用 Realm Web SDK 和 Next.js 服务器端呈现的过程如下:

  1. 在浏览器中,创建 App Services 客户端的实例并登录用户。将用户的 accessToken 保存为 cookie。此示例使用包 nookies ,这简化了 Next.js 应用中的 Cookie 管理。

  2. 在服务器上,解析 accessToken Cookie 并使用它通过 Atlas GraphQL API 从 MongoDB 获取数据。

  3. 在服务器上,先将 MongoDB 中的数据预呈现到网页中,然后再发送到浏览器。

注意

请勿将 MongoDB 数据访问与服务器端呈现结合使用

虽然可以在服务器端环境中使用 MongoDB 数据访问来查询 MongoDB,但通常不建议这样做。您需要在浏览器中保存用户档案,以便在每次请求时传递给服务器,这是个安全漏洞。此外,MongoDB 数据访问从用户对象发出请求,而用户对象需要在每次请求时重新实例化和重新认证。

以下步骤概述了如何使用 Realm Web SDK 和 Next.js 服务器端进行渲染。

1

安装以下 npm 程序包:

npm install nookies
npm install @apollo/client graphql
2

创建自定义 App 页面包装器。创建文件 pages/_app.js,并使用 useApp() 钩子获取 Realm.App 实例。

如果当前有用户已通过身份验证,则将其 accessToken 保存为 cookie。这样一来,每次请求时将把 accessToken 从浏览器传输到服务器。在 useEffect 钩子中设置 cookie,每次用户对象更改时都会运行该钩子,如下所示。setInterval 还会在令牌过期前重置 cookie 中的档案。

import { useApp } from "../components/useApp";
import { setCookie } from "nookies";
// Import the useEffect hook
import { useEffect } from "react";
function MyApp({ Component, pageProps }) {
const app = useApp();
// Reset the user access token in cookies on a regular interval
useEffect(() => {
const user = app?.currentUser;
if (user) {
setCookie(null, "accessToken", user.accessToken);
// Refresh token before session expires
const TWENTY_MIN_MS = 1200000;
const resetAccessToken = setInterval(async () => {
await app?.currentUser?.refreshCustomData();
setCookie(null, "accessToken", user.accessToken);
}, TWENTY_MIN_MS);
// Clear interval setting access token whenever component unmounts or
// there's a change in user.
return () => clearInterval(resetAccessToken);
}
}, [app, app?.currentUser]);
return (
<>
<Component {...pageProps} app={app} />
</>
);
}
export default MyApp;
3

创建新的页面文件来执行服务器端呈现。在页面上添加代码,执行以下操作:

  1. 导入相关依赖项。

  2. 添加一个函数,该函数使用用户当前的身份验证令牌在每个请求上创建服务器端 GraphQL 客户端。

  3. 创建服务器用来获取数据的 GraphQL 请求。

  4. 使用 Next.js getServerSideProps 函数来执行以下操作:

    1. 从 Cookie 中解析访问令牌。

    2. 使用访问令牌创建 GraphQL 客户端。

    3. 运行该 GraphQL 查询。

    4. 返回用于服务器端呈现的数据。

  5. 导出页面组件以呈现数据。

总之,服务器端的呈现页面如下所示:

// 1. import dependencies
import nookies from "nookies";
import { ApolloClient, InMemoryCache, HttpLink, gql } from "@apollo/client";
// 2. Function to create GraphQL client
const createClient = (token) =>
new ApolloClient({
link: new HttpLink({
ssrMode: true,
uri: process.env.NEXT_PUBLIC_GRAPHQL_API_ENDPOINT,
headers: {
Authorization: `Bearer ${token}`,
},
}),
cache: new InMemoryCache(),
});
// 3. GraphQL Query used in SSR
const GET_PLANT = gql`
query Plant($name: String!) {
plant(query: { name: $name }) {
_id
sunlight
name
color
type
_partition
}
}
`;
// 4. Server-side logic to parse cookie and run query
export async function getServerSideProps(context) {
const { accessToken } = nookies.get(context);
const client = createClient(accessToken);
const {
data: { plant: lily },
} = await client.query({
query: GET_PLANT,
variables: { name: "daffodil" },
});
return {
props: { lily },
};
}
// Full page exported that gets the data from SSR
export default function Ssr({ lily }) {
return (
<div>
<h1>Data from Server-Side Rendering</h1>
{lily ? (
<div>
<p>{lily.name}</p>
<p>{lily.color}</p>
</div>
) : (
"no plant"
)}
</div>
);
}

您可以使用 Next.js 静态呈现和 Realm Web SDK 从 MondoDB Atlas 中提取数据,并在构建时生成页面 HTML。

您可能希望在以下用例中使用带有静态呈现的 Realm Web SDK:

  • 提取内容管理系统数据

  • 添加配置信息

  • 创建国际化内容

1

您需要创建服务器 API 密钥用于身份验证。按照 API 密钥配置页面上的步骤完成此步骤。然后,在 Next.js 应用中,将 API 密钥添加到 .env.local 文件中。只要不以 PUBLIC_NEXT_ 为前缀,就无法从浏览器访问存储的变量。

.env.local
REALM_API_KEY=secret_api_key

现在您可以在应用程序中访问变量,客户端呈现除外。

const { REALM_API_KEY } = process.env;
2

您可以使用 Next.js 函数 getStaticProps() 在静态生成期间查询 MongoDB。

如需使用 getStaticProps() 预呈现页面,请将 Next.js 应用程序连接到 Realm Web SDK。然后就可以使用 getStaticProps() 从 MongoDB 抓取数据。以下示例展示了如何使用静态呈现来查询 MongoDB。

import * as Realm from "realm-web";
export async function getStaticProps() {
const apiKey = process.env.REALM_API_KEY;
const app = new Realm.App({ id: process.env.NEXT_PUBLIC_APP_ID });
// Log in user using realm API key
const credentials = Realm.Credentials.apiKey(apiKey);
const user = await app.logIn(credentials);
// Connect to database
const mongo = user.mongoClient("mongodb-atlas");
const plants = mongo.db("example").collection("plants");
// Use plants.findOne to query the database
const data = await plants.findOne({ name: "daffodil" });
// You must parse data as JSON to use it as a prop
const json = JSON.parse(JSON.stringify(data));
return {
props: {
plant: json,
},
};
}
export default function Static({ plant }) {
return (
<div>
<h1>Data from Static Rendering</h1>
<div>
<div>
<p>{plant.name}</p>
<p>{plant.color}</p>
</div>
</div>
</div>
);
}

除 Realm Web SDK 之外,您还可以通过多种方式从 Next.js 查询 MongoDB:

← Apollo 客户端 (React) — Web SDK