Skip to content

Commit

Permalink
Revert "Eagerly load post metadata"
Browse files Browse the repository at this point in the history
This reverts commit 783c8ef.
  • Loading branch information
silvenon committed Mar 31, 2024
1 parent 09d1652 commit 2f62d0a
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 127 deletions.
246 changes: 132 additions & 114 deletions app/routes/_index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useLoaderData, Link, useRouteError } from '@remix-run/react'
import { useLoaderData, Link, useRouteError, Await } from '@remix-run/react'
import type {
MetaFunction,
LoaderFunctionArgs,
HeadersFunction,
} from '@remix-run/node'
import { json } from '@remix-run/node'
import { Fragment } from 'react'
import { defer } from '@remix-run/node'
import { Fragment, Suspense } from 'react'
import PostDate from '~/components/PostDate'
import ProfilePhoto from '~/components/ProfilePhoto'
import Prose from '~/components/Prose'
Expand All @@ -16,9 +16,15 @@ import circuitBoard from '~/images/circuit-board.svg'
import spriteUrl from '~/sprite.svg'
import clsx from 'clsx'

export async function loader(_: LoaderFunctionArgs) {
const entries = await getAllPostsMeta()
return json({ entries })
export function loader(_: LoaderFunctionArgs) {
return defer(
{ entries: getAllPostsMeta() },
{
headers: {
'Cache-Control': 'public, max-age=3600',
},
},
)
}

export const headers: HeadersFunction = ({ loaderHeaders }) => {
Expand All @@ -43,7 +49,7 @@ export const meta: MetaFunction = () => {
}

export default function Home() {
const { entries } = useLoaderData<typeof loader>()
const data = useLoaderData<typeof loader>()
return (
<>
<section className="relative mb-10 mt-4 border-b-2 border-t-2 border-purple-400 bg-purple-300 px-4 dark:border-purple-400 dark:bg-purple-800">
Expand Down Expand Up @@ -93,125 +99,137 @@ export default function Home() {
<main className="mt-6 md:pb-4">
<Prose>
<h2>Posts</h2>
{entries.map((entry, index) => {
const rule = index < entries.length - 1 ? <hr /> : null
<Suspense
fallback={<div aria-label="Loading" className="loader pl-2" />}
>
<Await resolve={data.entries}>
{(entries) =>
entries.map((entry, index) => {
const rule = index < entries.length - 1 ? <hr /> : null

if ('source' in entry) {
if ('parts' in entry) {
const externalSeries = entry
return (
<Fragment key={externalSeries.title}>
<article>
<h3>{externalSeries.title}</h3>
<PostDate
published={externalSeries.parts[0].published}
/>
<p>{externalSeries.description}</p>
<p>Parts of this series:</p>
<ol>
{externalSeries.parts.map((part) => (
<li key={part.title} className="space-x-2">
<span className="dark:text-white">
{part.title}
</span>
<span>·</span>
<a
href={part.url}
target="_blank"
rel="noreferrer"
className="inline-flex items-center space-x-2"
>
<span>Read on {externalSeries.source}</span>
<svg aria-hidden="true" className="h-6 w-6">
<use href={`${spriteUrl}#external`} />
</svg>
</a>
</li>
))}
</ol>
</article>
{rule}
</Fragment>
)
}

if ('source' in entry) {
if ('parts' in entry) {
const externalSeries = entry
return (
<Fragment key={externalSeries.title}>
<article>
<h3>{externalSeries.title}</h3>
<PostDate published={externalSeries.parts[0].published} />
<p>{externalSeries.description}</p>
<p>Parts of this series:</p>
<ol>
{externalSeries.parts.map((part) => (
<li key={part.title} className="space-x-2">
<span className="dark:text-white">
{part.title}
</span>
<span>·</span>
const externalPost = entry
return (
<Fragment key={externalPost.title}>
<article>
<h3>
<a
href={externalPost.url}
target="_blank"
rel="noreferrer"
>
{externalPost.title}
</a>
</h3>
<PostDate published={externalPost.published} />
<p>{externalPost.description}</p>
<p>
<a
href={part.url}
href={externalPost.url}
target="_blank"
rel="noreferrer"
className="inline-flex items-center space-x-2"
>
<span>Read on {externalSeries.source}</span>
<span>Read on {externalPost.source}</span>
<svg aria-hidden="true" className="h-6 w-6">
<use href={`${spriteUrl}#external`} />
</svg>
</a>
</li>
))}
</ol>
</article>
{rule}
</Fragment>
)
}
</p>
</article>
{rule}
</Fragment>
)
}

const externalPost = entry
return (
<Fragment key={externalPost.title}>
<article>
<h3>
<a
href={externalPost.url}
target="_blank"
rel="noreferrer"
>
{externalPost.title}
</a>
</h3>
<PostDate published={externalPost.published} />
<p>{externalPost.description}</p>
<p>
<a
href={externalPost.url}
target="_blank"
rel="noreferrer"
className="inline-flex items-center space-x-2"
>
<span>Read on {externalPost.source}</span>
<svg aria-hidden="true" className="h-6 w-6">
<use href={`${spriteUrl}#external`} />
</svg>
</a>
</p>
</article>
{rule}
</Fragment>
)
}

if ('parts' in entry) {
const series = entry
return (
<Fragment key={series.slug}>
<article>
<h3>
<Link to={`/blog/${series.slug}/${series.parts[0].slug}`}>
{series.title}
</Link>
</h3>
<PostDate published={series.published ?? undefined} />
<p>{series.description}</p>
<p>Parts of this series:</p>
<ol>
{series.parts.map((part) => (
<li key={part.slug}>
<Link to={`/blog/${series.slug}/${part.slug}`}>
{part.title}
</Link>
</li>
))}
</ol>
</article>
{rule}
</Fragment>
)
}
if ('parts' in entry) {
const series = entry
return (
<Fragment key={series.slug}>
<article>
<h3>
<Link
to={`/blog/${series.slug}/${series.parts[0].slug}`}
>
{series.title}
</Link>
</h3>
<PostDate published={series.published ?? undefined} />
<p>{series.description}</p>
<p>Parts of this series:</p>
<ol>
{series.parts.map((part) => (
<li key={part.slug}>
<Link to={`/blog/${series.slug}/${part.slug}`}>
{part.title}
</Link>
</li>
))}
</ol>
</article>
{rule}
</Fragment>
)
}

const post = entry
return (
<Fragment key={post.slug}>
<article>
<h3>
<Link to={`/blog/${post.slug}`}>{post.title}</Link>
</h3>
<PostDate published={post.published ?? undefined} />
<p>{post.description}</p>
<p>
<Link to={`/blog/${post.slug}`}>Read more →</Link>
</p>
</article>
{rule}
</Fragment>
)
})}
const post = entry
return (
<Fragment key={post.slug}>
<article>
<h3>
<Link to={`/blog/${post.slug}`}>{post.title}</Link>
</h3>
<PostDate published={post.published ?? undefined} />
<p>{post.description}</p>
<p>
<Link to={`/blog/${post.slug}`}>Read more →</Link>
</p>
</article>
{rule}
</Fragment>
)
})
}
</Await>
</Suspense>
</Prose>
</main>
</>
Expand Down
27 changes: 14 additions & 13 deletions app/utils/posts.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ import { basename, dirname, join as joinPath } from 'path'

const standalonePostFrontmatter = import.meta.glob<StandalonePostFrontmattter>(
'/posts/*.mdx',
{ import: 'frontmatter', eager: true },
{ import: 'frontmatter' },
)
const seriesPostFrontmatter = import.meta.glob<SeriesPostFrontmatter>(
'/posts/*/*.mdx',
{ import: 'frontmatter', eager: true },
{ import: 'frontmatter' },
)
const seriesMeta = import.meta.glob<SeriesMeta>('/posts/*/series.json', {
import: 'default',
eager: true,
})

export interface StandalonePostFrontmattter {
Expand Down Expand Up @@ -127,7 +126,7 @@ export async function getAllPostsMeta() {
...externalPosts,
...Object.keys(standalonePostFrontmatter).map(async (path) => {
const slug = basename(path, '.mdx')
const meta = standalonePostFrontmatter[path]
const meta = await standalonePostFrontmatter[path]()
const result: StandalonePostFrontmattter & {
slug: string
fileModified?: string
Expand Down Expand Up @@ -174,11 +173,11 @@ export async function getAllPostsMeta() {
})
}

export function getStandalonePostMeta(slug: string) {
export async function getStandalonePostMeta(slug: string) {
const path = `/posts/${slug}.mdx`
const isStandalonePost = path in standalonePostFrontmatter
if (!isStandalonePost) return null
const frontmatter = standalonePostFrontmatter[path]
const frontmatter = await standalonePostFrontmatter[path]()
const isPublished = 'published' in frontmatter
if (!isPublished && !import.meta.env.DEV) return null
return frontmatter
Expand All @@ -188,18 +187,20 @@ export async function getSeriesMeta(slug: string) {
const seriesPath = `/posts/${slug}/series.json`
const isSeries = seriesPath in seriesMeta
if (!isSeries) return null
const meta = seriesMeta[seriesPath]
const meta = await seriesMeta[seriesPath]()
const isPublished = 'published' in meta
if (!isPublished && !import.meta.env.DEV) return null
const partPaths = Object.keys(seriesPostFrontmatter).filter((postPath) =>
postPath.startsWith(`/posts/${slug}/`),
)
const parts = partPaths
.map((postPath) => ({
slug: basename(postPath, '.mdx'),
...seriesPostFrontmatter[postPath],
}))
.sort((a, b) => a.seriesPart - b.seriesPart)
const parts = await Promise.all(
partPaths.map(async (postPath) => {
const meta = await seriesPostFrontmatter[postPath]()
return { slug: basename(postPath, '.mdx'), ...meta }
}),
).then((parts) => {
return parts.sort((a, b) => a.seriesPart - b.seriesPart)
})

const result: SeriesMeta & {
slug: string
Expand Down

0 comments on commit 2f62d0a

Please sign in to comment.