Next.js 集成指南 — Web SDK
GraphQL已弃用。 了解详情。
以下指南解释了如何将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 获取数据,从而在构建时生成页面。
开始之前
使用本集成指南之前,您应该:
熟悉 Next.js。 请考虑参阅 Next.js 文档。
创建 Next.js 应用。 如果是首次创建 Next.js 应用程序,请参阅 Next.js 教程。
在 Next.js 应用程序中添加 Realm Web SDK。有关详细信息,请参阅“Realm Web 安装”文档。
提示
MongoDB Atlas Vercel 集成
如果使用 Vercel 托管 Next.js 应用,请添加 MongoDB Atlas 集成以轻松将 Next.js 应用连接到 Atlas。
添加身份验证
从应用查询 MongoDB 之前,您必须初始化 App Services 客户端并对用户进行身份验证。您可以按照以下步骤将 Realm Web SDK 连接到客户端 Next.js。
在此示例中,我们将在自定义 React Hook 中使用 Realm.getApp() 在整个应用中公开经过身份验证的 Realm.App
实例。
创建 React 钩子来获取应用程序
客户端使用 React 钩子来实例化和访问 Realm.App,你可以使用应用程序 ID 连接到 App Services。您将在本指南中创建的所有页面中使用这个钩子。
创建文件
components/useApp.js
。添加以下代码来实例化和访问
App
实例:
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; }
登录用户
现在您可以使用 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。
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
或者可以使用 Atlas GraphQL API 从 Next.js 客户端代码通过 GraphQL 查询 MongoDB。
此示例使用 Apollo GraphQL 客户端 执行 GraphQL 查询。安装 Apollo 客户端及其npm 包 @apollo/client 及其对等依赖GraphQL 。
npm install @apollo/client graphql
现在您可以添加一个页面来执行 GraphQL 查询。页面中的代码会执行以下操作:
导入必要的依赖项
在提供商组件中创建 GraphQL 客户端。
定义该 GraphQL 查询。
创建组件,用于消耗 GraphQL 提供程序并运行查询。
导出包装消费者组件的提供者组件。
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 服务器端呈现的过程如下:
在浏览器中,创建Atlas App Services客户端实例并登录用户。 将用户的 accessToken 保存为 cookie。 此示例使用包 nookies ,这简化了 Next.js 应用中的 Cookie 管理。
在服务器上,解析 accessToken Cookie 并使用它通过 Atlas GraphQL API 从 MongoDB 获取数据。
在服务器上,先将 MongoDB 中的数据预呈现到网页中,然后再发送到浏览器。
注意
请勿将 MongoDB 数据访问与服务器端呈现结合使用
虽然可以在服务器端环境中使用 MongoDB 数据访问来查询 MongoDB,但通常不建议这样做。您需要在浏览器中保存用户档案,以便在每次请求时传递给服务器,这是个安全漏洞。此外,MongoDB 数据访问从用户对象发出请求,而用户对象需要在每次请求时重新实例化和重新认证。
以下步骤概述了如何使用 Realm Web SDK 和 Next.js 服务器端进行渲染。
创建自定义应用程序包装器,为 cookie 添加 accessToken
创建自定义 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;
服务器端呈现数据
创建新的页面文件来执行服务器端呈现。在页面上添加代码,执行以下操作:
导入相关依赖项。
添加一个函数,该函数使用用户当前的身份验证令牌在每个请求上创建服务器端 GraphQL 客户端。
创建服务器用来获取数据的 GraphQL 请求。
使用 Next.js getServerSideProps 函数执行以下操作:
从 Cookie 中解析访问令牌。
使用访问令牌创建 GraphQL 客户端。
运行该 GraphQL 查询。
返回用于服务器端呈现的数据。
导出页面组件以呈现数据。
总之,服务器端的呈现页面如下所示:
// 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:
提取内容管理系统数据
添加配置信息
创建国际化内容
使用getStaticProps()
执行静态渲染。
你可以使用 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> ); }
从 Next.js 查询 MongoDB 的替代方法
除 Realm Web SDK 之外,您还可以通过多种方式从 Next.js 查询 MongoDB:
将 MongoDB 与 Next.js 应用程序集成,然后使用 MongoDB 节点驱动程序执行 MongoDB 查询。 有关更多信息,请参阅博文“如何将 MongoDB 集成到您的 Next.js 应用程序中”。 使用MongoDB驱动程序与Atlas App Services基于用户的规则和权限不兼容。
使用MongoDB Atlas Data API从 Next.js 服务器查询MongoDB Atlas 。 有关更多信息,请参阅Atlas Data API端点。