Next.js认证库深度对比:Clerk vs Kinde vs Better Auth

本文详细对比了三种流行的Next.js认证库Clerk、Kinde和Better Auth,包含完整的环境配置、代码示例和使用场景分析,帮助开发者选择最适合项目的认证解决方案。

Clerk vs Kinde vs Better Auth:如何选择合适的Next.js认证库

认证是构建应用程序时的重要方面,特别是当应用涉及金融信息或需要用户登录账户时。构建认证库需要大量工作,既然已有许多高效的库存在,就没有必要重新发明轮子。

在本文中,我们将比较一些可以在Next应用中使用的认证库,包括:Clerk、Kinde和Better Auth。您将学习如何在Next.js应用程序中设置这些工具,目标是创建至少一个经过认证的受保护页面路由。

这里的目的是简单了解每个工具在设置速度和易用性方面的表现。

目录

Clerk、Kinde和Better Auth是什么?

Clerk、Kinde和Better Auth基本上是现代认证提供商,类似于Auth.js,它们都是为开发人员构建的。尽管它们有相似之处,但某些方面使它们彼此区别。

首先,Clerk功能更全面。它更像是一个托管解决方案,提供现成的组件、用户管理和其他集成,让您可以快速启动和运行。

另一方面,Kinde更像是一个开发人员平台,将认证、功能标志和团队管理集中在一个地方。

Better Auth更像是一个开源和代码优先的平台,为开发人员提供构建块来创建认证,而不必被锁定在某个生态系统中。

先决条件

本教程的先决条件很少,数据库和Prisma ORM仅适用于Better Auth。或者,您可以在Docker容器中使用任何数据库,而不是在本地安装,但这超出了本教程的范围。

您需要以下内容来跟随学习:

  • 已安装Node和npm
  • Prisma ORM
  • 在本地设置的SQLite、PostgreSQL或MySQL数据库
  • 代码编辑器/IDE

让我们看看如何在Next.js应用程序中设置所有三个认证平台的认证。我们将使用单独的Next.js应用程序来设置每个库,这样代码库将保持干净,您可以体验从头开始设置它们的感觉。

首先,确定项目的位置,例如在桌面上,然后使用命令npx create-next-app@latest设置Next.js项目。您可以使用默认配置。以下是我使用的设置:

1
2
3
4
5
6
7
8
✔ What is your project named? … my-app
✔ Would you like to use TypeScript? … No / Yes
✔ Which linter would you like to use? › ESLint
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like your code inside a src/ directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to use Turbopack? (recommended) … No / Yes
✔ Would you like to customize the import alias (@/* by default)? … No / Yes

我们正在创建三个应用程序,所以如果您想现在复制代码库并给它们不同的名称,如my-app、my-app2和my-app3,或者在我们到达每个部分时再进行操作,这取决于您。

如何使用Clerk设置认证

设置好Next.js项目后,cd进入my-app文件夹或您给项目的任何名称,并运行以下命令安装Clerk的Next.js SDK:

1
npm install @clerk/nextjs

现在我们需要创建一个中间件文件,以便在整个应用程序中授予用户认证访问权限。

在/src文件夹内创建一个middleware.ts文件,其中包含以下代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import { clerkMiddleware } from '@clerk/nextjs/server'

export default clerkMiddleware()

export const config = {
  matcher: [
    // 跳过Next.js内部文件和所有静态文件,除非在搜索参数中找到
    '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
    // 始终为API路由运行
    '/(api|trpc)(.*)',
  ],
}

有了这个文件,认证就为不同的页面路由设置好了。

剩下的就是将<ClerkProvider>组件添加到您的应用程序的layout.tsx文件中,以便在整个应用程序中提供认证。

只需用以下代码替换src/app/layout.tsx中的所有代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import type { Metadata } from 'next';
import { Geist, Geist_Mono } from 'next/font/google';
import './globals.css';
import {
  ClerkProvider,
  SignInButton,
  SignUpButton,
  SignedIn,
  SignedOut,
  UserButton,
} from '@clerk/nextjs';

const geistSans = Geist({
  variable: '--font-geist-sans',
  subsets: ['latin'],
});

const geistMono = Geist_Mono({
  variable: '--font-geist-mono',
  subsets: ['latin'],
});

export const metadata: Metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <ClerkProvider>
      <html lang="en">
        <body
          className={`${geistSans.variable} ${geistMono.variable} antialiased`}
        >
          <header className="flex justify-end items-center p-4 gap-4 h-16">
            <SignedOut>
              <SignInButton />
              <SignUpButton>
                <button className="bg-[#6c47ff] text-white rounded-full font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 cursor-pointer">
                  Sign Up
                </button>
              </SignUpButton>
            </SignedOut>
            <SignedIn>
              <UserButton />
            </SignedIn>
          </header>
          {children}
        </body>
      </html>
    </ClerkProvider>
  );
}

我们所做的是导入ClerkProvider,以及使用Clerk认证的登录和退出按钮。这些添加已添加到layout.tsx文件中,这意味着它们在整个应用程序中都可用。因此,每个页面都应在页面顶部显示登录流程。

ClerkProvider组件需要用于在我们的应用程序中集成Clerk,所以现在我们可以使用Clerk的钩子和组件的会话和用户上下文。

现在您可以使用npm run dev运行Next.js应用程序,您应该看到主页,以及页面顶部的登录和注册按钮,如下所示:

点击注册按钮将带您到一个注册表单,您可以在其中使用电子邮件地址或使用Google登录,这非常简单。

当您登录后,您应该在屏幕的右上角看到您的个人资料图片和账户信息。困难的部分已经完成 - 剩下的就是创建一个页面,然后使路由受保护,以便只有登录的用户才能访问它。

首先,让我们用一些代码更新我们的middleware.ts文件,这些代码让我们可以保护路由:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'

const isProtectedRoute = createRouteMatcher(['/dashboard(.*)'])

export default clerkMiddleware(async (auth, req) => {
  if (isProtectedRoute(req)) await auth.protect()
})

export const config = {
  matcher: [
    // 跳过Next.js内部文件和所有静态文件,除非在搜索参数中找到
    '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
    // 始终为API路由运行
    '/(api|trpc)(.*)',
  ],
}

我们添加了一些新的导入用于createRouteMatcher,这是一个Clerk辅助函数,它赋予我们保护多个路由的能力。在这种情况下,我们应用程序中的仪表板页面路由要求用户登录才能访问该路由。现在我们需要创建一个仪表板页面。在app文件夹内创建此文件夹和文件:dashboard/page.tsx。然后通过给它一些代码来完成页面,如下所示:

1
2
3
4
5
6
7
export default function Dashboard() {
  return (
    <>
      <h1>Dashboard Page</h1>
    </>
  );
}

我们创建了一个简单的页面,其中有一个标题写着"Dashboard Page"。

恭喜,您已成功将认证添加到您的Next应用程序并保护了一个页面路由,而且只花了几个步骤!当您作为未登录用户导航到http://localhost:3000/dashboard时,您应该被重定向到一个登录表单,如下所示:

如果您已经登录,那么您应该看到仪表板页面。您可以使用Clerk官方文档了解更多信息。

如何使用Kinde设置认证

如果尚未完成,请为此项目创建另一个Next.js应用程序。Kinde将要求您在其平台上创建一个账户,然后才能使用其认证库。让我们完成注册过程。

首先,转到Kinde网站,您应该看到一个写着"Start for free"或类似的按钮。

点击该按钮应带您到一个页面,您可以在其中创建一个账户:

可能需要电子邮件代码验证:

在下一个屏幕上,您应该能够输入您的业务详细信息,可以是任何您想要的内容。每次为应用程序设置认证时,您都必须在您的账户上为其创建一个应用程序。给它任何您想要的名称,如app-clerk-test3272346214。相同的名称将用于业务和域。

在下一个屏幕上,我们将选择使用现有的代码库,因为我们有一个本地项目:

代码库在Next.js中,所以从列表中选择它:

下一个重要步骤是选择用户将如何登录。我选择了电子邮件和Google。您可以选择任何您想要的选项:

现在,在最后一个屏幕上,选择按照自己的节奏探索。

最后,我们到达了仪表板屏幕。

查看详细信息可以让您看到您的应用程序密钥和环境变量,以及其他有用的信息。

漫长的部分已经完成,让我们开始编写一些代码。导航到您的项目文件夹,然后安装Kinde的包:

1
npm i @kinde-oss/kinde-auth-nextjs

现在,创建一个.env.local文件,并将其放在项目的根文件夹中,其中包含您的环境变量。您可以在应用程序的"Quick Start"页面找到您的环境变量。

这是一个示例:

1
2
3
4
5
6
KINDE_CLIENT_ID=<your_kinde_client_id>
KINDE_CLIENT_SECRET=<your_kinde_client_secret>

KINDE_SITE_URL=http://localhost:3000
KINDE_POST_LOGOUT_REDIRECT_URL=http://localhost:3000
KINDE_POST_LOGIN_REDIRECT_URL=http://localhost:3000/dashboard

接下来,您需要创建以下API端点和文件夹结构及文件,如这里所示src/app/api/auth/[kindeAuth]/route.ts。

这是route.ts文件所需的代码:

1
2
3
import {handleAuth} from "@kinde-oss/kinde-auth-nextjs/server";

export const GET = handleAuth();

有了这段代码,Kinde现在可以在我们的应用程序内处理认证端点。

再次,您需要一个middleware.ts文件,以便在您的应用程序中正确设置认证。该文件应位于根目录中,并需要添加以下代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import { withAuth } from "@kinde-oss/kinde-auth-nextjs/middleware";

export default function middleware(req) {
  return withAuth(req);
}

export const config = {
  matcher: [
    // 在所有内容上运行,但Next内部文件和静态文件除外
    '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
  ]
};

像之前一样,我们现在可以用这个文件保护页面路由。您的应用程序必须包装在Kinde Auth Provider中,以便您可以在整个应用程序中访问数据。

在app目录中创建一个AuthProvider.tsx文件,其中包含以下代码:

1
2
3
4
5
6
"use client";
import {KindeProvider} from "@kinde-oss/kinde-auth-nextjs";

export const AuthProvider = ({children}) => {
  return <KindeProvider>{children}</KindeProvider>;
};

Kinde使用React Context Provider通过KindeProvider组件在我们的整个应用程序中维护其内部状态。

接下来,替换和更新layout.tsx文件,使其包装在Auth Provider中:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import type { Metadata } from 'next';
import { Geist, Geist_Mono } from 'next/font/google';
import './globals.css';
import { AuthProvider } from './AuthProvider';
import {
  RegisterLink,
  LoginLink,
  LogoutLink,
} from '@kinde-oss/kinde-auth-nextjs/components';

const geistSans = Geist({
  variable: '--font-geist-sans',
  subsets: ['latin'],
});

const geistMono = Geist_Mono({
  variable: '--font-geist-mono',
  subsets: ['latin'],
});

export const metadata: Metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <AuthProvider>
      <div className="grid grid-flow-col gap2">
        <LoginLink>Sign in</LoginLink>
        <RegisterLink>Sign up</RegisterLink>
        <LogoutLink>Log out</LogoutLink>
      </div>
      <html lang="en">
        <body
          className={`${geistSans.variable} ${geistMono.variable} antialiased`}
        >
          {children}
        </body>
      </html>
    </AuthProvider>
  );
}

在这个文件中,我们还添加了注册、登录和退出的按钮,这些按钮将显示在每个页面的顶部,因为这是主要的layout.tsx文件。我们的AuthProvider组件包装在我们的应用程序周围,这意味着我们现在可以在整个应用程序中使用Kinde。

基本设置现已完成!运行通常的命令启动Next.js应用程序,您应该会在屏幕顶部看到登录流程按钮。

您应该能够注册并创建一个账户。这样做会将您重定向到仪表板屏幕,该屏幕显示404错误页面。这是因为我们尚未创建仪表板页面。

这是Kinde注册表单的样子:

这是Kinde登录表单的样子:

现在只剩下一步:为您的认证创建一个受保护的路由。

为您的仪表板页面创建以下文件结构和文件:src/app/dashboard/page.tsx。

然后将此代码添加到文件中:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
'use client';

import { useKindeBrowserClient } from '@kinde-oss/kinde-auth-nextjs';
import { LoginLink } from '@kinde-oss/kinde-auth-nextjs/components';

export default function Dashboard() {
  const { isAuthenticated, isLoading } = useKindeBrowserClient();

  if (isLoading) return <div>Loading...</div>;

  return isAuthenticated ? (
    <div>
      <p>
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque ut
        ante enim. Maecenas ut eros nec diam vulputate sollicitudin. Cras ut
        quam leo. Pellentesque semper, lacus sodales gravida suscipit, metus
        quam congue eros, nec sagittis est dolor eu turpis. Nulla congue
        tristique venenatis. Donec ac venenatis mauris. Donec commodo cursus
        magna, vitae tincidunt magna vestibulum eget.
      </p>
    </div>
  ) : (
    <div>
      You have to <LoginLink>Login</LoginLink> to see this page
    </div>
  );
}

此页面文件检查用户是否经过认证和登录。如果他们已登录,他们会看到Lorem ipsum文本,如果他们未登录,他们会看到一条消息,告诉他们必须登录才能看到该页面。

您只需作为登录或退出用户前往仪表板路由即可亲眼看到。这基本上就是使用Kinde平台进行认证的基础知识。请参阅在线文档以了解有关它的一切。

如何使用Better Auth设置认证

最后,让我们创建一个使用Better Auth的项目。Better Auth需要一个数据库来存储用户数据,因此设置需要更多步骤。您可以在此处找到安装指南,但我们也将在此处介绍。

好的,就像之前一样,如果尚未完成,请创建一个Next.js项目,然后使用以下命令安装better-auth包:

1
npm install better-auth

接下来,您必须设置环境变量,因此创建一个.env文件,其中包含以下值:

1
2
BETTER_AUTH_SECRET= #创建您自己的密钥!
BETTER_AUTH_URL=http://localhost:3000 # 您应用程序的基本URL

确保您创建一个密钥,就像生成一个包含大写和小写字母及数字的安全密码一样。

让我们设置Prisma包和PostgreSQL数据库,因此运行这些脚本来初始化它们:

1
2
3
npm install prisma --save-dev
npx prisma init
npm install @prisma/client

在下一步中,我们必须创建一个更好的认证实例。在这种情况下,我们将文件放在src/lib/auth.ts中。

因此创建一个auth.ts文件,其中包含以下代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import { betterAuth } from 'better-auth';
import { anonymous } from 'better-auth/plugins';
import { prismaAdapter } from 'better-auth/adapters/prisma';
// 如果您的Prisma文件位于其他地方,您可以更改路径
import { PrismaClient } from '@/generated/prisma';

const prisma = new PrismaClient();
export const auth = betterAuth({
  database: prismaAdapter(prisma, {
    provider: 'postgresql', // 或 "mysql", "postgresql", ...等等
  }),
  plugins: [anonymous()],
});

在这个文件中,我们配置了Better Auth以使用Prisma ORM进行数据库连接,并且我们将连接到PostgreSQL数据库。如果您愿意,可以将其更改为不同的数据库,但设置可能会不同,所以请记住这一点。如果您知道如何设置,也可以使用Docker。匿名登录是用户的默认设置。

现在我们需要创建数据库表来保存用户信息,因此在终端中使用此命令来执行此操作:

1
npx @better-auth/cli generate

您可能会看到此警告,只需使用"y"选择是:

1
2
prisma:warn In production, we recommend using `prisma generate --no-engine` (See: `prisma generate --help`)
✔ The file ./prisma/schema.prisma already exists. Do you want to overwrite the schema to the file? … yes

为了处理API请求,我们必须在服务器上设置一个路由处理程序。为route.ts文件创建一个文件夹结构和文件,如这里所示/app/api/auth/[…all]/route.ts。

将以下代码添加到文件中:

1
2
3
4
import { auth } from '@/lib/auth'; // 到您的认证文件的路径
import { toNextJsHandler } from 'better-auth/next-js';

export const { POST, GET } = toNextJsHandler(auth);

此文件允许您处理认证文件的POST和GET请求。

最后,我们必须创建一个lib/auth-client.ts文件。此文件允许您与认证服务器交互,并且它有一个插件,因此用户可以匿名登录。

以下是放入此文件的代码:

1
2
3
4
5
6
7
import { createAuthClient } from 'better-auth/react';
import { anonymousClient } from 'better-auth/client/plugins';
export const authClient = createAuthClient({
  /** 服务器的基本URL(如果使用相同域,则可选) */
  baseURL: 'http://localhost:3000',
  plugins: [anonymousClient()],
});

有了这个文件,用户就可以匿名登录,甚至无需创建账户或使用社交登录,这要归功于该插件。

剩下的就是创建另一个具有认证功能的仪表板页面,就像之前一样。创建另一个具有此结构的仪表板页面:app/dashboard/page.tsx,然后将此代码添加到文件中:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
'use client';

import { useState, useEffect } from 'react';
import { authClient } from '@/lib/auth-client';

type User = {
  id: string;
  email: string;
  emailVerified: boolean;
  name: string;
  createdAt: Date;
  updatedAt: Date;
  image?: string | null;
  isAnonymous?: boolean | null;
};

export default function Dashboard() {
  const [user, setUser] = useState<User | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [isSigningIn, setIsSigningIn] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const checkAuth = async () => {
      try {
        const session = await authClient.getSession();
        if (session.data?.user) {
          setUser(session.data.user);
        }
      } catch (err) {
        console.error('Auth check error:', err);
      } finally {
        setIsLoading(false);
      }
    };

    checkAuth();
  }, []);

  const handleAnonymousSignIn = async () => {
    try {
      setIsSigningIn(true);
      setError(null);

      const result = await authClient.signIn.anonymous();

      if (result.data) {
        setUser(result.data.user);
        console.log('Anonymous user signed in:', result.data.user);
      } else if (result.error) {
        setError(result.error.message || 'Failed to sign in anonymously');
      }
    } catch (err) {
      setError('An unexpected error occurred');
      console.error('Anonymous sign-in error:', err);
    } finally {
      setIsSigningIn(false);
    }
  };

  const handleSignOut = async () => {
    try {
      await authClient.signOut();
      setUser(null);
    } catch (err) {
      console.error('Sign out error:', err);
    }
  };

  if (isLoading) {
    return (
      <div className="max-w-4xl mx-auto p-6">
        <div className="flex items-center justify-center min-h-[400px]">
          <div className="text-center">
            <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500 mx-auto mb-4"></div>
            <p className="text-gray-600">Checking authentication...</p>
          </div>
        </div>
      </div>
    );
  }

  if (!user) {
    return (
      <div className="max-w-4xl mx-auto p-6">
        <div className="text-center">
          <h1 className="text-3xl font-bold mb-6">Access Required</h1>
          <p className="text-gray-600 mb-8">
            You need to be signed in to access our dashboard. Choose an option
            below to continue.
          </p>

          {error && (
            <div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-6 max-w-md mx-auto">
              {error}
            </div>
          )}

          <div className="bg-gray-50 p-8 rounded-lg border max-w-md mx-auto">
            <h2 className="text-xl font-semibold mb-4 text-black">
              Sign In Options
            </h2>

            <button
              onClick={handleAnonymousSignIn}
              disabled={isSigningIn}
              className="w-full bg-blue-500 hover:bg-blue-600 disabled:bg-blue-300 text-white px-6 py-3 rounded font-medium mb-4"
            >
              {isSigningIn ? 'Signing in...' : 'Sign In Anonymously'}
            </button>

            <p className="text-sm text-gray-500 mb-4">
              Anonymous access allows you to use our dashboard without creating
              an account. You can always link your account later.
            </p>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="max-w-4xl mx-auto p-6">
      <div className="bg-green-50 border border-green-200 rounded-lg p-4 mb-6">
        <div className="flex items-center justify-between">
          <div>
            <h2 className="text-lg font-semibold text-green-800">
              Welcome, {user.isAnonymous ? 'Anonymous User' : user.name}!
            </h2>
            <p className="text-sm text-green-600">
              {user.isAnonymous
                ? 'You are signed in anonymously'
                : `Signed in as ${user.email}`}
            </p>
          </div>
          <button
            onClick={handleSignOut}
            className="bg-red-500 hover:bg-red-600 text-white px-4 py-2 rounded text-sm"
          >
            Sign Out
          </button>
        </div>
      </div>

      <h1 className="text-3xl font-bold mb-6">Dashboard</h1>

      {process.env.NODE_ENV === 'development' && (
        <div className="mt-8 bg-gray-100 p-4 rounded-lg">
          <h3 className="font-semibold mb-2 text-black">Debug Info:</h3>
          <pre className="text-xs text-gray-600 overflow-auto">
            {JSON.stringify(user, null, 2)}
          </pre>
        </div>
      )}
    </div>
  );
}

此代码创建了一个仪表板页面,要求用户经过认证和登录才能使用它。在用户匿名登录后,他们可以查看有关其个人资料的一些调试信息。因此,基本上,此页面是我们仪表板视图的认证流程,它与我们的自定义authClient集成。此页面还处理匿名用户的加载错误状态和退出。

好的,现在我们可能需要再次重置Prisma数据库,否则可能会遇到模式和表错误。

首先,确保您的Prisma开发数据库正在运行,使用此命令:

1
npx prisma dev

然后运行这些命令来重置数据库并应用模式的新迁移:

1
2
npx prisma migrate reset
npx prisma migrate dev

您可能需要重新启动Prisma开发服务器,然后使用命令npx prisma dev运行它。

我们的Better Auth应用程序需要运行两个服务器。

  • Prisma开发服务器
  • Next.js应用程序

在Prisma开发服务器运行的情况下,您现在可以使用通常的命令npm run dev启动Next.js应用程序。

如果您遇到Prisma ORM或数据库的任何问题,例如表丢失或模式不匹配,那么这里有一些有用的命令,希望能解决它们。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# ⚠️ 警告:这将删除数据库,重新创建它,并从头开始应用所有迁移。
npx prisma migrate reset

# 应用任何尚未运行的新迁移(或者如果您的模式发生更改,则创建一个新的迁移)。
npx prisma migrate dev

# 启动Prisma Studio(用于探索和编辑数据库的GUI)。
npx prisma dev

# 运行Better Auth CLI迁移(设置认证所需的任何数据库表/更改)。
npx @better-auth/cli migrate

这些命令是不言自明的,让我们在数据库发生更改时运行迁移,并且我们可以在Prisma Studio中查看我们的数据库。

这是用户未登录时仪表板页面的样子:

登录后将显示仪表板屏幕。要了解有关Better Auth的更多信息,您可以阅读其官方文档。

何时使用每个库

这些认证库各有优缺点,可以根据您的项目需求适应各种需求。知道何时使用每个库可以更好地为真实世界条件和生产环境构建做好准备,所以让我们来看看它们并进行比较。

何时使用Clerk

当您需要快速使用认证而不必担心管理多个服务器,并且需要使用预制的界面和管理系统时,Clerk表现出色。它非常适合初创公司和希望优先考虑开发人员体验和快速实施的团队。

它具有简化且用户友好的设置,仍然能够支持最基本的要素,因此对于必须具有简单实施的小型团队和项目来说,这是一个非常好的选择。如果您正在构建一个SaaS,需要从一开始就有良好的界面和组件,或者如果您需要社交登录而无需大量代码,那么这是一个非常好的解决方案,特别是如果您在小型项目中需要速度和成本效益。

何时使用Kinde

当您热衷于拥有透明的定价和更快的框架集成认证时,Kinde是一个绝佳的选择。Kinde被设计为Clerk的成本效益替代品,提供更透明的定价和更慷慨的免费层级。

它非常适合需要可靠认证选项但希望降低成本和更好框架支持的团队。Kinde在用于需要比基本认证系统更多但也不需要企业级工具的中型项目时非常有效。

何时使用Better Auth

当您需要开箱即用的广泛功能集时,Better Auth是一个很好的解决方案。还值得注意的是,Better Auth有一个插件生态系统,可以用几行代码简化添加更高级的功能。在本文讨论的所有选项中,Better Auth是迄今为止最干净的;但是,它需要更多的编码知识和技能。

如果您正在构建TypeScript应用程序并希望完全控制自定义和认证数据流,这是一个很好的选择。该框架是不可知的,并具有2FA、多租户支持和其他复杂功能等功能,因此开发人员可以充分利用该工具,因为没有供应商锁定。通过插件生态系统可以轻松扩展功能,因此开发人员可以根据自己的需求进行定制。

结论

所有三个平台都相当擅长它们的工作,我毫不怀疑它们将继续成为向我们的应用程序添加认证的流行选项。Auth.js是其中最著名的之一;然而,Clerk、Kinde和Better Auth似乎也有越来越多的追随者,根据社交媒体的对话判断,它们似乎是目前许多开发人员的首选。

在体验了第一次设置它们的感觉之后,我不得不说Clerk是最容易设置的,因为您不必创建账户,并且可以通过很少的故障排除相当快地使认证工作。在我看来,Kinde是第二容易设置的。您确实必须注册一个账户才能使用该平台;但是,设置也相当容易,不需要任何故障排除。

Better Auth是一个很棒的平台,但设置需要更多的工作,因为需要一个数据库来存储用户信息,这使得过程稍微困难一些。我还发现使用其他两个认证选项创建认证路由更容易。然而,该平台是开源的,没有供应商锁定,这对其有利,因为开发人员可以自托管,并且它是完全免费的,这意味着没有付费计划。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计