主頁 > 企業開發 > 使用Nextjs快速開發全堆疊導航網站

使用Nextjs快速開發全堆疊導航網站

2023-06-17 08:07:54 企業開發

背景

隨著ChatGPT的火熱,國外很多開發者快速回應,應用于不同場景的AI應用井噴式的爆發,并且基本集中在web領域應用,而在快速開發的背后,我們可以看到,開發者大多選擇Next.js或者Nuxt.js全堆疊框架來開發,以快速驗證自己的產品,這種選型的背后,我覺得主要原因有:

  • SEO的重要性

    國外更加注重SEO的重要性,國內搜索引擎大多是靠花錢買搜索流量,包括小程式、App這類對SEO的需求并不大

  • Edge Function的興起

    Serverless使得前端開發能快速開發全堆疊應用,方便的托管自己后端服務,而不用過多關注部署,然而他的缺點是,多數Serverless都是采用容器化的方案,因此冷啟動時間長,如果在自己的云函式轉發請求OpenAI介面,可能會發生請求時間很長的情況,如今, Vercel、CloudFlare、Supabase等廠商都有了Edge Function的能力,使得函式可以在一些距離用戶更近的邊緣節點運行,為了更快的冷啟動時間來快速回應用戶,這種方案一般也加了部分限制,但是依舊得到很多開發者的青睞

  • 云服務廠商的多樣性

    云服務廠商提供了很多基礎服務,當把專案托管給Vercel等服務時,可以與Github集成進行持續部署,同時還會分配一個域名,很多其他廠商也提供了很多的免費后端存盤服務,例如:

    • Upsatsh提供的Redis
    • Supabase提供的PostgreSQL
    • PlantScale提供的MySQL
    • Clerk提供的用戶認證和用戶管理

以上這些廠商的免費計劃對于個人開發完全夠用,當然也可以根據產品規模使用付費計劃

而本文旨在嘗試開發一個簡單的導航頁面,滿足自己的收集癖好,用于解放自己的收藏夾,來學習Next.js開發,體驗Next.js帶來的開發全堆疊應用的便捷性,你可以打開頁面體驗,也可以在本專案開源地址查看完整代碼,

初始化專案

隨著以tailwindcssunocss這種原子化CSS方案的出現,基于此衍生出來的UI組件庫也很多,比如Radix、daisyUI、flowbite, 其中的RadixUI組件庫相當注重網頁的可訪問性,組件都遵循WAI-ARIA標準,這使得開發者構建可訪問的UI界面變得更加容易,而因為他專注于可訪問性、屬于Headless UI也就是無具體樣式類名代碼,因此shadcn作者開發了shadcn/ui組件庫,在此RadixUI組件庫基礎上賦予了簡潔美觀的樣式,得到了很多開發者的青睞, 也非常推薦大家體驗下,

這里直接選擇克隆該作者的Nextjs模版初始化專案

git clone https://github.com/shadcn/next-template

該專案使用了Next.js最新的app router版本,并且已經集成了tailwindcssshadcn/ui組件庫,這里選擇做導航網站也是因為它足夠簡單,關鍵樣式是針對側邊欄,因為tailwindcss是移動端優先,所以這里設定默認隱藏,當螢屏寬度大于sm時展示,

<div className="fixed z-20 hidden min-h-screen sm:block">
	...
</div>

而對于串列區域,采用grid布局,默認移動端優先一列,根據螢屏大小展示2列或者3

<div className="grid grid-cols-1 gap-3 md:grid-cols-2 md:gap-6 lg:grid-cols-3">
   ...
</div>

其他的樣式可以借鑒一下別人的網站設計簡單美化下,對于不太熟悉css并且缺乏審美的我花了不少的時間在調整,總覺得網站不夠美觀,但是又不知道該如何美化,

資料庫集成

定義模型

資料庫集成這里我選擇了Prisma,類似的比較熱門的還有Drizzle,針對Prisma的具體概念、使用和它的優點,可以參考我整理記錄的筆記,執行

npx prisma init

會創建prisma/schema.prisma檔案,創建模型如下

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

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

model Category {
  id          String   @id @default(cuid())
  icon        String
  title       String
  description String
  rank        Int?
  createdAt   DateTime @default(now()) @map(name: "created_at")
  updatedAt   DateTime @default(now()) @map(name: "updated_at")
  links       Link[]

  @@map(name: "category")
}

model Link {
  id          String   @id @default(cuid())
  icon        String
  url         String
  title       String
  description String
  rank        Int?
  public      Boolean  @default(true)
  status      Int      @default(1) @db.TinyInt
  createdAt   DateTime @default(now()) @map(name: "created_at")
  updatedAt   DateTime @default(now()) @map(name: "updated_at")
  cid         String
  catagory    Category @relation(fields: [cid], references: [id])

  @@map(name: "link")
}

其中DATABASE_URL為遠程資料庫地址,這里我使用的是PlantScaleMySQL,當然你也可以使用SupabasePostgreSQL或者其他資料庫,創建.env檔案,填入服務地址

https://img.uj5u.com/2023/06/17/355078170740541.png

DATABASE_URL='mysql://user:[email protected]/dev?sslaccept=strict'

可以在這個可視化Prisma模型網站看到關系圖如下, 分別表示類別實體和網站鏈接實體

https://img.uj5u.com/2023/06/17/355078170740542.png

表同步

然后執行命令將本地模型同步到資料庫表

npx prisma db push

然后可能會遇到下面報錯

https://img.uj5u.com/2023/06/17/355078170740543.png

查閱后發現官網在檔案中有說明,PlanetScale的MySQL資料庫不支持外鍵,需要特殊的指定relationMode

datasource db {
  provider     = "mysql"
  url          = env("DATABASE_URL")
  relationMode = "prisma"
}

relationMode默認值是foreignKeys,當使用PlanetScale資料庫的MySQL連接器時,應啟用此選項, 在Prisma Client中模擬關系,再次執行db push指令,將模型同步到資料庫

https://img.uj5u.com/2023/06/17/355078170740544.png

插入和查詢資料

然后執行

npx prisma studio

打開表編輯器添加自己的資料

https://img.uj5u.com/2023/06/17/355078170740545.png

執行命令生成PrismaClient實體

pnpm install @prisma/client
npx prisma generate

然后就可以通過關聯關系一次性查詢出資料

import prisma from '@/lib/db';
import type { Prisma } from '@prisma/client';

export default async function getNavLinks() {
  const res = await prisma.category.findMany({
    orderBy: [
      {
        rank: 'asc',
      }
    ],
    include: {
      links: {
        orderBy: {
          rank: 'asc',
        },
        where: {
          public: true,
          status: 1,
        },
      },
    },
  });
  return res;
}

export type CategoryWithLinks = Prisma.PromiseReturnType<typeof getNavLinks>

用戶認證

Next.js中集成用戶認證非常簡單,可以直接使用NextAuth

NextAuth

NextAuth是一個為Next.js應用程式提供的開源身份驗證解決方案,默認情況下,NextAuth使用JSON Web Tokens(JWT)保存用戶會話,NextAuth支持流行的登錄服務,如GoogleFacebookAuth0Apple、電子郵件以及OAuth 1.02.0服務等等,是一種靈活可配置的身份驗證解決方案,

首先安裝所需依賴

pnpm install next-auth @next-auth/prisma-adapter

按照官方檔案指引添加用戶相關模型

model Account {
  id                 String  @id @default(cuid())
  userId             String
  type               String
  provider           String
  providerAccountId  String
  refresh_token      String?  @db.Text
  access_token       String?  @db.Text
  expires_at         Int?
  token_type         String?
  scope              String?
  id_token           String?  @db.Text
  session_state      String?

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAccountId])
}

model Session {
  id           String   @id @default(cuid())
  sessionToken String   @unique
  userId       String
  expires      DateTime
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model User {
  id            String    @id @default(cuid())
  name          String?
  email         String?   @unique
  emailVerified DateTime?
  image         String?
  accounts      Account[]
  sessions      Session[]
}

model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime

  @@unique([identifier, token])
}

GitHub

獲取Github客戶端ID,參考檔案,包含以下步驟:

  1. 打開GitHub應用程式頁面,點擊創建Github應用,

    https://img.uj5u.com/2023/06/17/355078170740546.png

  2. 輸入名稱、主頁、以及授權后的回呼地址,這里開發環境時填localhost:3000,上線時切換成自己的線上域名即可,

    https://img.uj5u.com/2023/06/17/355078170740547.png

  3. 點擊”生成”并保存Client IDClient Secret

    https://img.uj5u.com/2023/06/17/355078170740548.png

Google

參考NextAuth檔案指引,在Google開發者網站注冊應用并選擇api服務

https://img.uj5u.com/2023/06/17/355078170740549.png

應用型別選擇Web應用,類似Github填上可信任的域名和回呼地址確認

https://img.uj5u.com/2023/06/17/3550781707405410.png

創建 API 路由

首先在.env檔案中添加上面保存的認證相關密鑰,其中NEXTAUTH_SECRET是用戶生成JWT的密鑰

# google登錄
GOOGLE_CLIENT_ID="GOOGLE_CLIENT_ID"
GOOGLE_CLIENT_SECRET="GOOGLE_CLIENT_SECRET"

# github登錄
GITHUB_CLIENT_ID="GITHUB_CLIENT_ID"
GITHUB_CLIENT_SECRET="GITHUB_CLIENT_SECRET"

NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="webnav"

可以看到上面的API回呼地址分別是/api/auth/github/api/auth/google, 創建app/api/auth/[…nextauth]/route.ts 檔案,并添加以下代碼片段:

import NextAuth, { type NextAuthOptions } from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import GitHubProvider from "next-auth/providers/github";
import CredentialsProvider from "next-auth/providers/credentials";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import { PrismaClient } from "@prisma/client";
import { compare } from "bcrypt";

const prisma = new PrismaClient();

export const authOptions: NextAuthOptions = {
  adapter: PrismaAdapter(prisma),
  providers: [
    GitHubProvider({
      clientId: process.env.GITHUB_CLIENT_ID!,
      clientSecret: process.env.GITHUB_CLIENT_SECRET!,
    }),
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    }),
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials) {
        const { email, password } = credentials ?? {}
        if (!email || !password) {
          throw new Error("Missing username or password");
        }
        const user = await prisma.user.findUnique({
          where: {
            email: credentials?.email,
          },
        });
        // if user doesn't exist or password doesn't match
        if (!user || !(await compare(password, user.password!))) {
          throw new Error("Invalid username or password");
        }
        return user;
      },
    })
  ],
  session: {
    strategy: "jwt",
  },
  debug: process.env.NODE_ENV !== "production",
};

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST };

其中,GitHubProvider用戶Github登錄,GoogleProvider用于Google登錄,CredentialsProvider用于自定義登錄,這里會檢查郵箱密碼, 匹配上了就回傳用戶資訊,

同時還需要創建注冊登錄頁面,創建app/login/page.tsx檔案和app/register/page.tsx 檔案,頁面直接復制的taxonomy 頁面樣式,自己加上google登錄按鈕,效果如圖

https://img.uj5u.com/2023/06/17/3550781707405411.png

頁面上通過

import { signIn, signOut } from "next-auth/react"

signIn方法允許使用GoogleGitHub帳戶進行登錄, signOut允許注銷用戶會話, 具體使用可以參考官方檔案這部分

部署

[Vercel](https://vercel.com/)中直接匯入專案,修改構建命令為

npx prisma generate && next build

build之前先生成PrismaClient型別,不然編譯時會因為型別報錯而失敗,同時添加.env中所需要的環境變數

https://img.uj5u.com/2023/06/17/3550781707405412.png

同時因為我們的資料源在資料庫,而Nextjs默認是構建時生成頁面的也就是SSG模式,在資料庫有資料更新時我們需要更新頁面內容,因此我們需要使用它的增量靜態生成ISR(Incremental Static Regeneration)模式,參考官方檔案,在page.tsx中添加匯出,這里對更新時效性要求不高所以設定為1

export const revalidate = 24 * 60 * 60;

從構建日志中可以看到已經生效了

https://img.uj5u.com/2023/06/17/3550781707405413.png

部署成功后系結自定義域名就完結撒花了,

總結

本文以簡單的導航網站舉例,結合Next.jsPrismaNextAuthshadcn/ui 來學習如何構建全堆疊應用,你可以打開頁面體驗,也可以在本專案開源地址查看完整代碼,最后碼字不易,如果你都看到這了,麻煩star一波,感謝,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/555400.html

標籤:其他

上一篇:【一步步開發AI運動小程式】十二、自定義一個運動分析器,實作計時計數01

下一篇:返回列表

標籤雲
其他(161158) Python(38236) JavaScript(25504) Java(18244) C(15237) 區塊鏈(8271) C#(7972) AI(7469) 爪哇(7425) MySQL(7254) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5875) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4599) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2436) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1984) HtmlCss(1968) 功能(1967) Web開發(1951) C++(1941) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1881) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Nextjs快速開發全堆疊導航網站

    # 背景 隨著`ChatGPT`的火熱,國外很多開發者快速回應,應用于不同場景的AI應用井噴式的爆發,并且基本集中在`web`領域應用,而在快速開發的背后,我們可以看到,開發者大多選擇`Next.js`或者`Nuxt.js`全堆疊框架來開發,以快速驗證自己的產品。這種選型的背后,我覺得主要原因有: - ......

    uj5u.com 2023-06-17 08:07:54 more
  • 【一步步開發AI運動小程式】十二、自定義一個運動分析器,實作計時

    > 隨著人工智能技術的不斷發展,阿里體育等IT大廠,推出的“樂動力”、“天天跳繩”AI運動APP,讓**云上運動會、線上運動會、健身打卡、AI體育指導**等概念空前火熱。那么,能否將這些在APP成功應用的場景搬上小程式,分享這些概念的紅利呢?本系列文章就帶您一步一步從零開始開發一個AI運動小程式,本 ......

    uj5u.com 2023-06-17 08:07:32 more
  • javaScript基礎語法之正則運算式

    ##正則運算式規則 | 運算式 | 描述 | | | | | [0-9] | 查找任何從 0 至 9 的數字。例如,匹配: '111' ,不匹配:'eee' | | [abc] | 查找方括號之間的任何字符。例如,/[123]/ 匹配 "1234567" 中的 "123","1" 中的 "1"。但是 ......

    uj5u.com 2023-06-17 08:07:17 more
  • TS中, Array.reduce提示沒有與此呼叫匹配的多載?

    起因 一個feature開發, 結果需求評審、工時預估, 簡直是事故級別的. 最后, 迫于無奈, 全組人都得上去救火... 今天, 幫忙改bug的時候, 發現新checkout下來的代碼, 還帶著新鮮的語法錯誤...簡直大無語. 翻了遍代碼, 發現很多地方都存在Array.reduce型別多載相關的 ......

    uj5u.com 2023-06-17 08:07:12 more
  • JavaScript 陣列展平方法: flat() 和 flatMap()

    從 ES2019 中開始引入了一種扁平化陣列的新方法,可以展平任何深度的陣列。 ### flat `flat()` 方法創建一個新陣列,其中所有子陣列元素以遞回方式連接到特定深度。 > 語法:array.flat(depth) - **array** : `flat()` 方法將在給定的陣列中使用。 ......

    uj5u.com 2023-06-17 08:07:08 more
  • js~在瀏覽器中對用戶名和密碼進行存盤

    # base64函式 `btoa()` 和 `atob()` 是 JavaScript 中的標準函式,通常在現代瀏覽器中都能正常作業。然而,它們在處理非 ASCII 字符時可能存在一些兼容性問題。 這些函式的主要限制在于它們僅支持 ASCII 字符集,對于非 ASCII 字符(如 Unicode 字 ......

    uj5u.com 2023-06-17 08:07:01 more
  • 什么是SEO

    SEO是搜索引擎優化的縮寫,它是一種通過優化網站和網頁,以提高其在搜索引擎中的排名和可見性的技術和實踐。 搜索引擎是人們在互聯網上查找資訊的主要工具,常見的搜索引擎包括Google、Bing和小度等。當用戶在搜索引擎中輸入關鍵詞或短語時,搜索引擎會根據其演算法和規則,顯示與這些關鍵詞相關的網頁串列,按 ......

    uj5u.com 2023-06-17 08:06:56 more
  • 【一步步開發AI運動小程式】十二、自定義一個運動分析器,實作計時

    > 隨著人工智能技術的不斷發展,阿里體育等IT大廠,推出的“樂動力”、“天天跳繩”AI運動APP,讓**云上運動會、線上運動會、健身打卡、AI體育指導**等概念空前火熱。那么,能否將這些在APP成功應用的場景搬上小程式,分享這些概念的紅利呢?本系列文章就帶您一步一步從零開始開發一個AI運動小程式,本 ......

    uj5u.com 2023-06-17 08:06:48 more
  • 前端基于 radio 增強單選框組件

    前端基于radio增強單選框組件, 下載完整代碼請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=12977 效果圖如下: # #### 使用方法 ```使用方法 <!-- radioData:單選資料 curIndex:當前選擇序列 @cha ......

    uj5u.com 2023-06-17 08:06:22 more
  • 驅動開發:內核RIP劫持實作DLL注入

    本章將探索內核級DLL模塊注入實作原理,DLL模塊注入在應用層中通常會使用`CreateRemoteThread`直接開啟遠程執行緒執行即可,驅動級別的注入有多種實作原理,而其中最簡單的一種實作方式則是通過劫持EIP的方式實作,其實作原理可總結為,掛起目標行程,停止目標行程EIP的變換,在目標行程開啟... ......

    uj5u.com 2023-06-17 08:05:55 more