Skip to content

Commit

Permalink
fix: repository page speed improvements (#3269)
Browse files Browse the repository at this point in the history
  • Loading branch information
nickytonline committed May 1, 2024
1 parent de99fef commit fcbf89d
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 46 deletions.
8 changes: 4 additions & 4 deletions components/Graphs/ForksChart.stories.tsx
Expand Up @@ -10,7 +10,7 @@ const meta: Meta<typeof ForksChart> = {
stats: generate30DaysData(),
range: 30,
total: 228,
syncId: "repo_id",
syncId: 1234,
isLoading: false,
},
};
Expand All @@ -22,7 +22,7 @@ export const Days30: Story = {
stats: generate30DaysData(),
range: 30,
total: 228,
syncId: "repo_id",
syncId: 1234,
},
};

Expand All @@ -31,7 +31,7 @@ export const Days7: Story = {
stats: generate7DaysData(),
range: 7,
total: 228,
syncId: "repo_id",
syncId: 1234,
},
};

Expand All @@ -40,7 +40,7 @@ export const Days90: Story = {
stats: generate90DaysData(),
range: 90,
total: 228,
syncId: "repo_id",
syncId: 1234,
},
};

Expand Down
2 changes: 1 addition & 1 deletion components/Graphs/ForksChart.tsx
Expand Up @@ -24,7 +24,7 @@ import SkeletonWrapper from "components/atoms/SkeletonLoader/skeleton-wrapper";
type ForksChartProps = {
stats: StatsType[] | undefined;
total: number;
syncId: string;
syncId: number;
range: DayRange;
isLoading: boolean;
};
Expand Down
8 changes: 4 additions & 4 deletions components/Graphs/StarsChart.stories.tsx
Expand Up @@ -10,7 +10,7 @@ const meta: Meta<typeof StarsChart> = {
stats: generate30DaysData(),
range: 30,
total: 3376,
syncId: "repo_id",
syncId: 1234,
isLoading: false,
},
};
Expand All @@ -22,7 +22,7 @@ export const Days30: Story = {
stats: generate30DaysData(),
range: 30,
total: 3376,
syncId: "repo_id",
syncId: 1234,
},
};

Expand All @@ -31,7 +31,7 @@ export const Days7: Story = {
stats: generate7DaysData(),
range: 7,
total: 3376,
syncId: "repo_id",
syncId: 1234,
},
};

Expand All @@ -40,7 +40,7 @@ export const Days90: Story = {
stats: generate90DaysData(),
range: 90,
total: 3376,
syncId: "repo_id",
syncId: 1234,
},
};

Expand Down
2 changes: 1 addition & 1 deletion components/Graphs/StarsChart.tsx
Expand Up @@ -24,7 +24,7 @@ import SkeletonWrapper from "components/atoms/SkeletonLoader/skeleton-wrapper";
type StarsChartProps = {
stats: StatsType[] | undefined;
total: number;
syncId: string;
syncId: number;
range: DayRange;
isLoading: boolean;
};
Expand Down
18 changes: 13 additions & 5 deletions components/Repositories/RepositoryOgImage.tsx
@@ -1,17 +1,25 @@
import SEO from "layouts/SEO/SEO";

export function getRepositoryOgImage(repository: DbRepo, range = 30) {
export function getRepositoryOgImage({
description,
fullRepoName,
range = 30,
}: {
description: string;
fullRepoName: string;
range: number;
}) {
const searchParams = new URLSearchParams();

if (repository.description.length > 0) {
searchParams.append("description", repository.description);
if (description?.length > 0) {
searchParams.append("description", description);
}

return `/og-images/repository/${repository.full_name}/${range}?${searchParams}`;
return `/og-images/repository/${fullRepoName}/${range}?${searchParams}`;
}

interface WorkspaceOgImageProps {
repository: DbRepo;
repository: DbRepoInfo;
ogImageUrl: string;
}

Expand Down
4 changes: 4 additions & 0 deletions lib/hooks/api/useFetchMetricStats.ts
Expand Up @@ -21,6 +21,10 @@ export function useFetchMetricStats({ repository, variant, range, orderDirection
query.set("orderDirection", orderDirection);

const endpoint = () => {
if (typeof window === "undefined") {
return null;
}

switch (variant) {
case "stars":
return `histogram/stars?${query}`;
Expand Down
19 changes: 19 additions & 0 deletions lib/hooks/api/useRepoStats.ts
@@ -0,0 +1,19 @@
import useSWR, { Fetcher } from "swr";
import { publicApiFetcher } from "lib/utils/public-api-fetcher";

export const useRepoStats = ({ repoFullName, range }: { repoFullName: string; range: number }) => {
const query = new URLSearchParams();
query.set("range", range.toString());

const { data, error, isLoading, mutate } = useSWR<DbRepo, Error>(
typeof window === "undefined" ? null : `repos/${repoFullName}?${query}`,
publicApiFetcher as Fetcher<DbRepo, Error>
);

return {
data,
isLoading: !error && !data,
isError: !!error,
mutate,
};
};
40 changes: 40 additions & 0 deletions next-types.d.ts
Expand Up @@ -8,6 +8,46 @@ declare module React {
}
}

interface DbRepoInfo {
readonly id: number;
readonly size: number;
readonly issues: number;
readonly stars: number;
readonly forks: number;
readonly watchers: number;
readonly subscribers: number;
readonly network: number;
readonly is_fork: boolean;
readonly is_private: boolean;
readonly is_template: boolean;
readonly is_archived: boolean;
readonly is_disabled: boolean;
readonly has_issues: boolean;
readonly has_projects: boolean;
readonly has_downloads: boolean;
readonly has_wiki: boolean;
readonly has_pages: boolean;
readonly has_discussions: boolean;
readonly created_at: string;
readonly updated_at: string;
readonly pushed_at: string;
readonly default_branch: string;
readonly node_id: string;
readonly git_url: string;
readonly ssh_url: string;
readonly clone_url: string;
readonly svn_url: string;
readonly mirror_url: string;
readonly name: string;
readonly full_name: string;
readonly description: string;
readonly language: string;
readonly license: string;
readonly url: string;
readonly homepage: string;
readonly topics: string[];
}

interface DbRepo {
readonly id: string;
readonly host_id: string;
Expand Down
73 changes: 42 additions & 31 deletions pages/s/[org]/[repo]/index.tsx
Expand Up @@ -17,44 +17,45 @@ import { getRepositoryOgImage, RepositoryOgImage } from "components/Repositories
import { useToast } from "lib/hooks/useToast";
import { shortenUrl } from "lib/utils/shorten-url";
import Button from "components/shared/Button/button";
import { getAvatarByUsername } from "lib/utils/github";
import { useRepoStats } from "lib/hooks/api/useRepoStats";

export async function getServerSideProps(context: GetServerSidePropsContext) {
const { org, repo } = context.params ?? { org: "", repo: "" };
const range = (context.query.range ? Number(context.query.range) : 30) as Range;

const { data: repoData, error } = await fetchApiData<DbRepo>({
path: `repos/${org}/${repo}?range=${range}`,
path: `repos/${org}/${repo}/info`,
});

if (!repoData || error) {
return { notFound: true };
}

const response = await fetch(repoData.url || `https://api.github.com/repos/${org}/${repo}`);
const { owner } = await response.json();

const { href: ogImageUrl } = new URL(
getRepositoryOgImage(repoData, range),
getRepositoryOgImage({
description: repoData.description,
fullRepoName: repoData.full_name,
range,
}),
process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000"
);

return { props: { repoData, image: owner?.avatar_url || "", ogImageUrl } };
// Cache for two hours
context.res.setHeader("Netlify-CDN-Cache-Control", "public, max-age=0, stale-while-revalidate=7200");

return { props: { repoData, ogImageUrl } };
}

type Range = 30 | 7 | 90 | 180 | 360;

interface RepoPageProps {
repoData: DbRepo;
image: string;
ogImageUrl: string;
}

interface WorkspaceOgImageProps {
repository: DbRepo;
repoData: DbRepoInfo;
ogImageUrl: string;
}

export default function RepoPage({ repoData, image, ogImageUrl }: RepoPageProps) {
export default function RepoPage({ repoData, ogImageUrl }: RepoPageProps) {
const avatarUrl = getAvatarByUsername(repoData.full_name.split("/")[0], 96);
const { toast } = useToast();
const posthog = usePostHog();

Expand All @@ -81,6 +82,8 @@ export default function RepoPage({ repoData, image, ogImageUrl }: RepoPageProps)
range,
});

const { data: repoStats, isError, isLoading } = useRepoStats({ repoFullName: repoData.full_name, range });

const starsRangedTotal = starsData?.reduce((prev, curr) => prev + curr.star_count!, 0);
const forksRangedTotal = forkStats?.reduce((prev, curr) => prev + curr.forks_count!, 0);

Expand All @@ -107,7 +110,7 @@ export default function RepoPage({ repoData, image, ogImageUrl }: RepoPageProps)
<section className="px-2 pt-2 md:pt-4 md:px-4 flex flex-col gap-2 md:gap-4 lg:gap-8 w-full xl:max-w-6xl">
<div className="flex flex-col lg:flex-row w-full justify-between items-center gap-4">
<header className="flex items-center gap-4">
<Avatar size={96} avatarURL={image} />
<Avatar size={96} avatarURL={avatarUrl} />
<div className="flex flex-col gap-2">
<a
href={`https://github.com/${repoData.full_name}`}
Expand Down Expand Up @@ -158,25 +161,33 @@ export default function RepoPage({ repoData, image, ogImageUrl }: RepoPageProps)
/>
<RepositoryStatCard
type="pulls"
isLoading={false}
hasError={false}
stats={{
opened: repoData.open_prs_count!,
merged: repoData.merged_prs_count!,
velocity: repoData.pr_velocity_count!,
range,
}}
isLoading={isLoading}
hasError={isError}
stats={
repoStats
? {
opened: repoStats.open_prs_count ?? 0,
merged: repoStats.merged_prs_count ?? 0,
velocity: repoStats.pr_velocity_count ?? 0,
range,
}
: undefined
}
/>
<RepositoryStatCard
type="issues"
isLoading={false}
hasError={false}
stats={{
opened: repoData.opened_issues_count!,
closed: repoData.closed_issues_count!,
velocity: repoData.issues_velocity_count!,
range,
}}
isLoading={isLoading}
hasError={isError}
stats={
repoStats
? {
opened: repoStats.opened_issues_count ?? 0,
closed: repoStats.closed_issues_count ?? 0,
velocity: repoStats.issues_velocity_count ?? 0,
range,
}
: undefined
}
/>
</section>
<StarsChart
Expand Down

0 comments on commit fcbf89d

Please sign in to comment.