設定 Next.js

先執行以下指令,使用supabase、typescript和tailwind初始化下一個js專案:npx create-next-app@latest。選擇所有預設選項:

設定 Prisma

執行以下命令安裝 prisma:

npm install prisma --save-dev

安裝 prisma 後,執行以下命令來初始化架構檔案和 .env 檔案:

npx 棱鏡熱

現在應該有一個 .env 檔案。您應該加入您的database_url 將 prisma 連接到您的資料庫。應該看起來像這樣:

// .env
DATABASE_URL=url

在你的 schema.prisma 中你應該要加入你的模型,我現在只是使用一些隨機模型:

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Post {
  id        String     @default(cuid()) @id
  title     String
  content   String?
  published Boolean @default(false)
  author    User?   @relation(fields: [authorId], references: [id])
  authorId  String?
}

model User {
  id            String       @default(cuid()) @id
  name          String?
  email         String?   @unique
  createdAt     DateTime  @default(now()) @map(name: "created_at")
  updatedAt     DateTime  @updatedAt @map(name: "updated_at")
  posts         Post[]
  @@map(name: "users")
}

現在您可以執行以下命令將資料庫與架構同步:

npx prisma 資料庫推送

為了在客戶端存取 prisma,您需要安裝 prisma 用戶端。您可以透過執行以下命令來執行此操作:

npm 安裝@prisma/client

您的客戶端也必須與您的架構同步,您可以透過執行以下命令來做到這一點:

npx prisma 生成

當您執行“npx prisma db push”時,會自動呼叫產生指令。

為了存取 prisma 用戶端,您需要建立它的一個實例,因此在 src 目錄中建立一個名為 lib 的新資料夾,並在其中新增一個名為 prisma.ts 的新檔案。

// prisma.ts

import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

export default prisma;

現在您可以在任何檔案中匯入相同的 Prisma 實例。

設定 Shadcn

首先執行以下命令開始設定 shadcn:

npx shadcn-ui@latest init

我選擇了以下選項:

打字稿:是的

風格:預設

底色: 板岩色

全域 CSS:src/app/globals.css

CSS 變數:是

順風配置:tailwind.config.ts

元件:@/元件(預設)

utils:@/lib/utils(預設)

反應伺服器元件:是

寫入 Components.json:是

接下來執行以下命令來設定下一個主題:

npm 安裝下一個主題

然後將一個名為 theme-provider.tsx 的檔案加入到您的元件庫中並新增以下程式碼:

// theme-provider.tsx

"use client"

import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
import { type ThemeProviderProps } from "next-themes/dist/types"

export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
  return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}

設定完提供者後,您需要將其新增至 layout.tsx 中,以便在整個應用程式上實現它。使用主題提供者包裝 {children},如下所示:

// layout.tsx
  return (
    <html lang="en" suppressHydrationWarning>
      <body className={inter.className}>
        <ThemeProvider
          attribute="class"
          defaultTheme="system"
          enableSystem
          disableTransitionOnChange
        >
          {children}
        </ThemeProvider>
      </body>
    </html>
  );

現在前往 shadcn 主題頁。然後選擇您要使用的主題並按複製程式碼。然後將複製的程式碼加入您的 globals.css 中,如下所示:

// globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
    --background: 0 0% 100%;
    --foreground: 224 71.4% 4.1%;
    --card: 0 0% 100%;
    --card-foreground: 224 71.4% 4.1%;
    --popover: 0 0% 100%;
    --popover-foreground: 224 71.4% 4.1%;
    --primary: 262.1 83.3% 57.8%;
    --primary-foreground: 210 20% 98%;
    --secondary: 220 14.3% 95.9%;
    --secondary-foreground: 220.9 39.3% 11%;
    --muted: 220 14.3% 95.9%;
    --muted-foreground: 220 8.9% 46.1%;
    --accent: 220 14.3% 95.9%;
    --accent-foreground: 220.9 39.3% 11%;
    --destructive: 0 84.2% 60.2%;
    --destructive-foreground: 210 20% 98%;
    --border: 220 13% 91%;
    --input: 220 13% 91%;
    --ring: 262.1 83.3% 57.8%;
    --radius: 0.5rem;
  }

  .dark {
    --background: 224 71.4% 4.1%;
    --foreground: 210 20% 98%;
    --card: 224 71.4% 4.1%;
    --card-foreground: 210 20% 98%;
    --popover: 224 71.4% 4.1%;
    --popover-foreground: 210 20% 98%;
    --primary: 263.4 70% 50.4%;
    --primary-foreground: 210 20% 98%;
    --secondary: 215 27.9% 16.9%;
    --secondary-foreground: 210 20% 98%;
    --muted: 215 27.9% 16.9%;
    --muted-foreground: 217.9 10.6% 64.9%;
    --accent: 215 27.9% 16.9%;
    --accent-foreground: 210 20% 98%;
    --destructive: 0 62.8% 30.6%;
    --destructive-foreground: 210 20% 98%;
    --border: 215 27.9% 16.9%;
    --input: 215 27.9% 16.9%;
    --ring: 263.4 70% 50.4%;
  }
}

現在您應該能夠在專案中使用 shadcn 元件和主題。

設定 Supabase

第一步是建立一個新的 SUPABASE 專案。接下來,安裝 next.js 驗證幫助程式庫:

npm install @supabase/auth-helpers-nextjs @supabase/supabase-js

現在您必須將您的 supabase url 和您的匿名金鑰新增至您的 .env 檔案中。您的 .env 檔案現在應如下所示:

// .env
DATABASE_URL=url
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key

我們將使用 supabase cli 根據我們的架構產生類型。使用以下命令安裝 cli:

npm install supabase --save-dev

為了登入 supabase,請執行“npx supabase login”,它會自動讓您登入。

現在我們可以透過執行以下命令來產生我們的類型:

npx supabase gen types typescript --project-id YOUR_PROJECT_ID > src/lib/database.types.ts 應該在您的 lib 資料夾中新增文件,其中包含基於您的架構的類型。

現在在專案的根目錄中建立一個 middleware.ts 檔案並新增以下程式碼:

import { createMiddlewareClient } from "@supabase/auth-helpers-nextjs";
import { NextResponse } from "next/server";

import type { NextRequest } from "next/server";
import type { Database } from "@/lib/database.types";

export async function middleware(req: NextRequest) {
  const res = NextResponse.next();
  const supabase = createMiddlewareClient<Database>({ req, res });
  await supabase.auth.getSession();
  return res;
}

現在,在應用程式目錄中建立一個名為 auth 的新資料夾,然後在 auth 中建立另一個名為callback 的資料夾,最後建立一個名為route.ts 的檔案。在該文件中加入以下程式碼:

// app/auth/callback/route.ts
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { NextResponse } from "next/server";

import type { NextRequest } from "next/server";
import type { Database } from "@/lib/database.types";

export async function GET(request: NextRequest) {
  const requestUrl = new URL(request.url);
  const code = requestUrl.searchParams.get("code");

  if (code) {
    const cookieStore = cookies();
    const supabase = createRouteHandlerClient<Database>({
      cookies: () => cookieStore,
    });
    await supabase.auth.exchangeCodeForSession(code);
  }

  // URL to redirect to after sign in process completes
  return NextResponse.redirect(requestUrl.origin);
}

透過該設置,我們可以建立一個登入頁面。在應用程式目錄中建立一個名為「login with page.tsx」的新資料夾。

// app/login/page.tsx
"use client";

import { createClientComponentClient } from "@supabase/auth-helpers-nextjs";
import { useRouter } from "next/navigation";
import { useState } from "react";

import type { Database } from "@/lib/database.types";

export default function Login() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const router = useRouter();
  const supabase = createClientComponentClient<Database>();

  const handleSignUp = async () => {
    await supabase.auth.signUp({
      email,
      password,
      options: {
        emailRedirectTo: `${location.origin}/auth/callback`,
      },
    });
    router.refresh();
  };

  const handleSignIn = async () => {
    await supabase.auth.signInWithPassword({
      email,
      password,
    });
    router.refresh();
  };

  const handleSignOut = async () => {
    await supabase.auth.signOut();
    router.refresh();
  };

  return (
    <>
      <input
        name="email"
        onChange={(e) => setEmail(e.target.value)}
        value={email}
      />
      <input
        type="password"
        name="password"
        onChange={(e) => setPassword(e.target.value)}
        value={password}
      />
      <button onClick={handleSignUp}>Sign up</button>
      <button onClick={handleSignIn}>Sign in</button>
      <button onClick={handleSignOut}>Sign out</button>
    </>
  );
}

現在,在 auth 目錄中建立一個名為「sign-up」的新資料夾,並在該檔案中建立一個「route.ts」。新增以下程式碼:

// app/auth/sign-up/route.ts
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { NextResponse } from "next/server";

import type { Database } from "@/lib/database.types";

export async function POST(request: Request) {
  const requestUrl = new URL(request.url);
  const formData = await request.formData();
  const email = String(formData.get("email"));
  const password = String(formData.get("password"));
  const cookieStore = cookies();
  const supabase = createRouteHandlerClient<Database>({
    cookies: () => cookieStore,
  });

  await supabase.auth.signUp({
    email,
    password,
    options: {
      emailRedirectTo: `${requestUrl.origin}/auth/callback`,
    },
  });

  return NextResponse.redirect(requestUrl.origin, {
    status: 301,
  });
}

在同一位置建立另一個名為「登入」的資料夾。

// app/auth/login/route.ts
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { NextResponse } from "next/server";

import type { Database } from "@/lib/database.types";

export async function POST(request: Request) {
  const requestUrl = new URL(request.url);
  const formData = await request.formData();
  const email = String(formData.get("email"));
  const password = String(formData.get("password"));
  const cookieStore = cookies();
  const supabase = createRouteHandlerClient<Database>({
    cookies: () => cookieStore,
  });

  await supabase.auth.signInWithPassword({
    email,
    password,
  });

  return NextResponse.redirect(requestUrl.origin, {
    status: 301,
  });
}

最後在同一位置新增註銷路由。

// app/auth/logout/route.ts
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'

import type { Database } from '@/lib/database.types'

export async function POST(request: Request) {
  const requestUrl = new URL(request.url)
  const cookieStore = cookies()
  const supabase = createRouteHandlerClient<Database>({ cookies: () => cookieStore })

  await supabase.auth.signOut()

  return NextResponse.redirect(`${requestUrl.origin}/login`, {
    status: 301,
  })
}

現在,當您導航至 localhost http://localhost:3000/login 時,應該有基本的登入登出註冊功能。

現在我們有了一些帶有 prisma shadcn 和 supabase auth 設定的下一個 js 應用程式的基本樣板。


原文出處:https://dev.to/isaacdyor/setting-up-nextjs-project-with-prisma-200j


共有 0 則留言