如何在Next.js使用Blitz.js的功能
前言
大家好,我是倔强青铜三。是一名热情的软件工程师,我热衷于分享和传播IT技术,致力于通过我的知识和技能推动技术交流与创新,欢迎关注我,微信公众号:倔强青铜三。欢迎点赞
、收藏
、关注
,一键三连!!!
@blitzjs/next
@blitzjs/next
适配器公开了特定于 Next.js 框架的函数和组件。
概览
@blitzjs/next
适配器公开了特定于 Next.js 框架的函数和组件。
安装
你可以通过运行以下命令来安装 @blitzjs/next
:
npm i @blitzjs/next # yarn add @blitzjs/next # pnpm add @blitzjs/next
Next 配置
Blitz.js 通过接受一个 blitz
属性来扩展 next.config.js
文件。
blitz?: {
resolverPath?: ResolverPathOptions;
customServer?: {
hotReload?: boolean;
};
};
注意事项
对于设置自定义 resolverPath
的更多信息,请查阅 RPC 规范。
客户端
示例
在 src/blitz-client.ts
中:
import { setupBlitzClient } from "@blitzjs/next"
export const { withBlitz } = setupBlitzClient({
plugins: [],
})
然后在 src/pages/_app.tsx
中用 withBlitz
高阶组件包裹 MyApp
函数。
import {
ErrorFallbackProps,
ErrorComponent,
ErrorBoundary,
} from "@blitzjs/next"
import { AuthenticationError, AuthorizationError } from "blitz"
import type { AppProps } from "next/app"
import React, { Suspense } from "react"
import { withBlitz } from "src/blitz-client"
function RootErrorFallback({ error }: ErrorFallbackProps) {
if (error instanceof AuthenticationError) {
return <div>Error: 您尚未认证</div>
} else if (error instanceof AuthorizationError) {
return (
<ErrorComponent
statusCode={error.statusCode}
title="抱歉,您无权访问此页面"
/>
)
} else {
return (
<ErrorComponent
statusCode={(error as any)?.statusCode || 400}
title={error.message || error.name}
/>
)
}
}
function MyApp({ Component, pageProps }: AppProps) {
return (
<ErrorBoundary FallbackComponent={RootErrorFallback}>
<Component {...pageProps} />
</ErrorBoundary>
)
}
export default withBlitz(MyApp)
注意事项
<ErrorBoundary />
提供商和 <ErrorComponent />
组件由 @blitzjs/next
提供。
API
setupBlitzClient({
plugins: [],
})
参数
plugins:
Blitz.js 插件数组- 必需
返回值
返回一个带有 withBlitz
HOC 包装器的对象
服务器端
示例
在 src/blitz-server.ts
中
import { setupBlitzServer } from "@blitzjs/next"
export const { gSSP, gSP, api } = setupBlitzServer({
plugins: [],
})
API
setupBlitzServer({
plugins: [],
onError?: (err) => void
})
参数
plugins:
Blitz.js 插件数组- 必需
onError:
捕获所有错误 (适用于 Sentry 等服务)
返回值
返回一个带有 gSSP
, gSP
和 api
包装器的对象。
自定义 Next.js 服务器
Blitz CLI 支持运行自定义 Next.js 服务器。这意味着你可以在 Blitz.js CLI 注入环境变量的同时编译 JavaScript 和 TypeScript。默认情况下,CLI 会检查 src/server/index.[ts | js]
或 src/server.[ts | js]
。
有关自定义 Next.js 服务器的更多信息,请查看 官方文档。
包装器
所有 Next.js 包装函数都使用 superjson 序列化。这意味着你可以在返回数据时使用 Date
, Map
, Set
和 BigInt
。另外需要注意的是,Blitz 在调用 Next.js 请求处理程序之前运行插件中的中间件。
注意事项
如果你使用认证插件,gSSP
, gSP
和 api
函数都会传递会话的上下文。有关认证插件的更多信息,请查阅 blitzjs/auth。
包装器示例
getStaticProps
import { gSP } from "src/blitz-server"
export const getStaticProps = gSP(async ({ ctx }) => {
return {
props: {
data: {
userId: ctx?.session.userId,
session: {
id: ctx?.session.userId,
publicData: ctx?.session.$publicData,
},
},
},
}
})
getServerSideProps
import { gSSP } from "src/blitz-server"
export const getServerSideProps = gSSP(async ({ ctx }) => {
return {
props: {
userId: ctx?.session.userId,
publicData: ctx?.session.$publicData,
},
}
})
api
import { api } from "src/blitz-server"
export default api(async (req, res, ctx) => {
res.status(200).json({ userId: ctx?.session.userId })
})
有关 Next.js API 路由的更多信息,请访问他们的文档:https://nextjs.org/docs/api-routes/introduction。
概念
页面加载前验证用户
你可能希望在页面加载前检查用户是否已登录。我们将在 getServerSideProps()
中直接调用查询。然后你可以在服务器端检查用户是否已登录,并使用内置的 Next.js 重定向属性。
import { Routes, BlitzPage } from "@blitzjs/next"
import { gSSP } from "src/blitz-server"
import getCurrentUser from "src/users/queries/getCurrentUser"
export const getServerSideProps = gSSP(async ({ ctx }) => {
const currentUser = await getCurrentUser(null, ctx)
if (currentUser) {
return {
props: {
user: currentUser,
},
}
} else {
return {
redirect: {
destination: Routes.LoginPage(),
permanent: false,
},
}
}
})
服务器端数据获取时的返回类型
你可以设置 Next.js 数据获取函数返回的类型。所有 Blitz.js 对 Next.js 函数的包装器都接受一个泛型。BlitzPage
类型也是如此。
例如,我们可以使用一些 TypeScript 工具来帮助获取 getCurrentUser()
返回的类型。
import { Routes, BlitzPage } from "@blitzjs/next"
import { gSSP } from "src/blitz-server"
import getCurrentUser from "src/users/queries/getCurrentUser"
type TCurrentUser = Awaited<ReturnType<typeof getCurrentUser>>
export const getServerSideProps = gSSP<{ user: TCurrentUser }>(
async ({ ctx }) => {
const currentUser = await getCurrentUser(null, ctx)
if (currentUser) {
return {
props: {
user: currentUser,
},
}
} else {
return {
redirect: {
destination: Routes.LoginPage(),
permanent: false,
},
}
}
}
)
const Page: BlitzPage<{ user: TCurrentUser }> = ({ user }) => {
return (
<Layout title="Page">
<div className="container">
<p>User Page</p>
{user && <p>{user.email}</p>}
</div>
</Layout>
)
}
export default Page
页面初始加载时处理错误
有一个边缘情况是,你可能在初始页面加载时调用的查询中抛出错误,导致服务器错误而不是触发 <ErrorBoundary />
。这是因为在 _app.tsx
挂载之前,初始加载页面时没有渲染 ErrorBoundary 组件。虽然这是预期的行为,但有一个解决办法。
例如,在一个查询中,如果用户未找到,你可以创建一个 NotFoundError()
然后返回状态码。
export default resolver.pipe(
resolver.zod(GetUser),
async (input) => {
const { id } = input
const user = await db.user.findFirst({ where: { id } })
if (!user) {
const userError = new NotFoundError("User not found")
return {
error: userError.statusCode,
}
} else {
return {
user,
}
}
}
)
然后在服务器端(例如 getServerSideProps()
)你可以调用查询,如果返回对象中找到错误键,则显示错误。
export const getServerSideProps = gSSP(async ({ ctx }) => {
const user = await getUser({ 1 }, ctx)
if ("error" in user) {
return { props: { error: user.error } }
} else {
return { props: { user } }
}
})
你也可以在 _app.tsx
中捕获服务器错误,并使用 toast 组件显示错误。
function MyApp({ Component, pageProps }: AppProps) {
const getLayout = Component.getLayout || ((page) => page)
if (pageProps.error) {
return <ToastComponent>{pageProps.error.statusCode}</ToastComponent>
}
return (
<ErrorBoundary FallbackComponent={RootErrorFallback}>
{getLayout(<Component {...pageProps} />)}
</ErrorBoundary>
)
}
最后感谢阅读!欢迎关注我,微信公众号:倔强青铜三
。欢迎点赞
、收藏
、关注
,一键三连!!!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。