Skip to content

Commit

Permalink
perf: refactor server data fetch
Browse files Browse the repository at this point in the history
  • Loading branch information
hamster1963 committed Dec 26, 2024
1 parent 0c3479b commit 6b52a8d
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 49 deletions.
17 changes: 5 additions & 12 deletions app/(main)/ClientComponents/detail/ServerDetailChartClient.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
"use client"

import { NezhaAPISafe, ServerApi } from "@/app/types/nezha-api"
import { useServerData } from "@/app/lib/server-data-context"
import { NezhaAPISafe } from "@/app/types/nezha-api"
import { ServerDetailChartLoading } from "@/components/loading/ServerDetailLoading"
import AnimatedCircularProgressBar from "@/components/ui/animated-circular-progress-bar"
import { Card, CardContent } from "@/components/ui/card"
import { ChartConfig, ChartContainer } from "@/components/ui/chart"
import { formatBytes, formatNezhaInfo, formatRelativeTime, nezhaFetcher } from "@/lib/utils"
import { formatBytes, formatNezhaInfo, formatRelativeTime } from "@/lib/utils"
import { useTranslations } from "next-intl"
import { useEffect, useState } from "react"
import { Area, AreaChart, CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts"
import useSWRImmutable from "swr/immutable"

type cpuChartData = {
timeStamp: string
Expand Down Expand Up @@ -52,16 +52,9 @@ export default function ServerDetailChartClient({
}) {
const t = useTranslations("ServerDetailChartClient")

const { data: allFallbackData } = useSWRImmutable<ServerApi>("/api/server", nezhaFetcher)
const fallbackData = allFallbackData?.result?.find((item) => item.id === server_id)
const { data: serverList, error } = useServerData()

const { data, error } = useSWRImmutable<NezhaAPISafe>(
`/api/detail?server_id=${server_id}`,
nezhaFetcher,
{
fallbackData,
},
)
const data = serverList?.result?.find((item) => item.id === server_id)

if (error) {
return (
Expand Down
24 changes: 5 additions & 19 deletions app/(main)/ClientComponents/detail/ServerDetailClient.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
"use client"

import { NezhaAPISafe, ServerApi } from "@/app/types/nezha-api"
import { useServerData } from "@/app/lib/server-data-context"
import { BackIcon } from "@/components/Icon"
import ServerFlag from "@/components/ServerFlag"
import { ServerDetailLoading } from "@/components/loading/ServerDetailLoading"
import { Badge } from "@/components/ui/badge"
import { Card, CardContent } from "@/components/ui/card"
import getEnv from "@/lib/env-entry"
import { cn, formatBytes, nezhaFetcher } from "@/lib/utils"
import { cn, formatBytes } from "@/lib/utils"
import { useTranslations } from "next-intl"
import { notFound, useRouter } from "next/navigation"
import { useEffect, useState } from "react"
import useSWR from "swr"
import useSWRImmutable from "swr/immutable"

export default function ServerDetailClient({ server_id }: { server_id: number }) {
const t = useTranslations("ServerDetailClient")
Expand All @@ -39,24 +36,13 @@ export default function ServerDetailClient({ server_id }: { server_id: number })
}
}

const { data: allFallbackData, isLoading } = useSWRImmutable<ServerApi>(
"/api/server",
nezhaFetcher,
)
const fallbackData = allFallbackData?.result?.find((item) => item.id === server_id)
const { data: serverList, error, isLoading } = useServerData()
const data = serverList?.result?.find((item) => item.id === server_id)

if (!fallbackData && !isLoading) {
if (!data && !isLoading) {
notFound()
}

const { data, error } = useSWR<NezhaAPISafe>(`/api/detail?server_id=${server_id}`, nezhaFetcher, {
refreshInterval: Number(getEnv("NEXT_PUBLIC_NezhaFetchInterval")) || 5000,
dedupingInterval: 1000,
fallbackData,
revalidateOnMount: false,
revalidateIfStale: false,
})

if (error) {
return (
<>
Expand Down
6 changes: 2 additions & 4 deletions app/(main)/ClientComponents/main/Global.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"use client"

import { ServerApi } from "@/app/types/nezha-api"
import { nezhaFetcher } from "@/lib/utils"
import useSWRImmutable from "swr/immutable"
import { useServerData } from "@/app/lib/server-data-context"

import GlobalLoading from "../../../../components/loading/GlobalLoading"
import { geoJsonString } from "../../../../lib/geo-json-string"
Expand All @@ -11,7 +9,7 @@ import GlobalInfo from "./GlobalInfo"
import { InteractiveMap } from "./InteractiveMap"

export default function ServerGlobal() {
const { data: nezhaServerList, error } = useSWRImmutable<ServerApi>("/api/server", nezhaFetcher)
const { data: nezhaServerList, error } = useServerData()

if (error)
return (
Expand Down
10 changes: 3 additions & 7 deletions app/(main)/ClientComponents/main/ServerListClient.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
"use client"

import { ServerApi } from "@/app/types/nezha-api"
import { useServerData } from "@/app/lib/server-data-context"
import ServerCard from "@/components/ServerCard"
import ServerCardInline from "@/components/ServerCardInline"
import Switch from "@/components/Switch"
import getEnv from "@/lib/env-entry"
import { useFilter } from "@/lib/network-filter-context"
import { useStatus } from "@/lib/status-context"
import { cn, nezhaFetcher } from "@/lib/utils"
import { cn } from "@/lib/utils"
import { MapIcon, ViewColumnsIcon } from "@heroicons/react/20/solid"
import { useTranslations } from "next-intl"
import dynamic from "next/dynamic"
import { useEffect, useRef, useState } from "react"
import useSWR from "swr"

import GlobalLoading from "../../../../components/loading/GlobalLoading"

Expand Down Expand Up @@ -70,10 +69,7 @@ export default function ServerListClient() {
}
}, [])

const { data, error } = useSWR<ServerApi>("/api/server", nezhaFetcher, {
refreshInterval: Number(getEnv("NEXT_PUBLIC_NezhaFetchInterval")) || 2000,
dedupingInterval: 1000,
})
const { data, error } = useServerData()

if (error)
return (
Expand Down
11 changes: 5 additions & 6 deletions app/(main)/ClientComponents/main/ServerOverviewClient.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
"use client"

import { ServerApi } from "@/app/types/nezha-api"
import { useServerData } from "@/app/lib/server-data-context"
import { Loader } from "@/components/loading/Loader"
import { Card, CardContent } from "@/components/ui/card"
import getEnv from "@/lib/env-entry"
import { useFilter } from "@/lib/network-filter-context"
import { useStatus } from "@/lib/status-context"
import { cn, formatBytes, nezhaFetcher } from "@/lib/utils"
import { cn, formatBytes } from "@/lib/utils"
import blogMan from "@/public/blog-man.webp"
import { ArrowDownCircleIcon, ArrowUpCircleIcon } from "@heroicons/react/20/solid"
import { useTranslations } from "next-intl"
import Image from "next/image"
import useSWRImmutable from "swr/immutable"

export default function ServerOverviewClient() {
const { data, error, isLoading } = useServerData()
const { status, setStatus } = useStatus()
const { filter, setFilter } = useFilter()
const t = useTranslations("ServerOverviewClient")

const { data, error, isLoading } = useSWRImmutable<ServerApi>("/api/server", nezhaFetcher)
const disableCartoon = getEnv("NEXT_PUBLIC_DisableCartoon") === "true"

if (error) {
const errorInfo = error as any
return (
<div className="flex flex-col items-center justify-center">
<p className="text-sm font-medium opacity-40">
Error status:{error.status} {error.info?.cause ?? error.message}
Error status:{errorInfo?.status} {errorInfo.info?.cause ?? errorInfo?.message}
</p>
<p className="text-sm font-medium opacity-40">{t("error_message")}</p>
</div>
Expand Down
5 changes: 4 additions & 1 deletion app/(main)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Footer from "@/app/(main)/footer"
import Header from "@/app/(main)/header"
import { ServerDataProvider } from "@/app/lib/server-data-context"
import { auth } from "@/auth"
import { SignIn } from "@/components/SignIn"
import getEnv from "@/lib/env-entry"
Expand All @@ -13,7 +14,9 @@ export default function MainLayout({ children }: DashboardProps) {
<div className="flex min-h-screen w-full flex-col">
<main className="flex min-h-[calc(100vh-calc(var(--spacing)*16))] flex-1 flex-col gap-4 bg-background p-4 md:p-10 md:pt-8">
<Header />
<AuthProtected>{children}</AuthProtected>
<AuthProtected>
<ServerDataProvider>{children}</ServerDataProvider>
</AuthProtected>
<Footer />
</main>
</div>
Expand Down
62 changes: 62 additions & 0 deletions app/lib/server-data-context.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"use client"

import { ServerApi } from "@/app/types/nezha-api"
import getEnv from "@/lib/env-entry"
import { nezhaFetcher } from "@/lib/utils"
import { ReactNode, createContext, useContext, useEffect, useState } from "react"
import useSWR from "swr"

interface ServerDataWithTimestamp {
timestamp: number
data: ServerApi
}

interface ServerDataContextType {
data: ServerApi | undefined
error: Error | undefined
isLoading: boolean
history: ServerDataWithTimestamp[]
}

const ServerDataContext = createContext<ServerDataContextType | undefined>(undefined)

const MAX_HISTORY_LENGTH = 30

export function ServerDataProvider({ children }: { children: ReactNode }) {
const [history, setHistory] = useState<ServerDataWithTimestamp[]>([])

const { data, error, isLoading } = useSWR<ServerApi>("/api/server", nezhaFetcher, {
refreshInterval: Number(getEnv("NEXT_PUBLIC_NezhaFetchInterval")) || 2000,
dedupingInterval: 1000,
})

useEffect(() => {
if (data) {
setHistory((prev) => {
const newHistory = [
{
timestamp: Date.now(),
data: data,
},
...prev,
].slice(0, MAX_HISTORY_LENGTH)

return newHistory
})
}
}, [data])

return (
<ServerDataContext.Provider value={{ data, error, isLoading, history }}>
{children}
</ServerDataContext.Provider>
)
}

export function useServerData() {
const context = useContext(ServerDataContext)
if (context === undefined) {
throw new Error("useServerData must be used within a ServerDataProvider")
}
return context
}

0 comments on commit 6b52a8d

Please sign in to comment.