Skip to content

Commit 2f62d0a

Browse files
committed
Revert "Eagerly load post metadata"
This reverts commit 783c8ef.
1 parent 09d1652 commit 2f62d0a

File tree

2 files changed

+146
-127
lines changed

2 files changed

+146
-127
lines changed

app/routes/_index.tsx

+132-114
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { useLoaderData, Link, useRouteError } from '@remix-run/react'
1+
import { useLoaderData, Link, useRouteError, Await } from '@remix-run/react'
22
import type {
33
MetaFunction,
44
LoaderFunctionArgs,
55
HeadersFunction,
66
} from '@remix-run/node'
7-
import { json } from '@remix-run/node'
8-
import { Fragment } from 'react'
7+
import { defer } from '@remix-run/node'
8+
import { Fragment, Suspense } from 'react'
99
import PostDate from '~/components/PostDate'
1010
import ProfilePhoto from '~/components/ProfilePhoto'
1111
import Prose from '~/components/Prose'
@@ -16,9 +16,15 @@ import circuitBoard from '~/images/circuit-board.svg'
1616
import spriteUrl from '~/sprite.svg'
1717
import clsx from 'clsx'
1818

19-
export async function loader(_: LoaderFunctionArgs) {
20-
const entries = await getAllPostsMeta()
21-
return json({ entries })
19+
export function loader(_: LoaderFunctionArgs) {
20+
return defer(
21+
{ entries: getAllPostsMeta() },
22+
{
23+
headers: {
24+
'Cache-Control': 'public, max-age=3600',
25+
},
26+
},
27+
)
2228
}
2329

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

4551
export default function Home() {
46-
const { entries } = useLoaderData<typeof loader>()
52+
const data = useLoaderData<typeof loader>()
4753
return (
4854
<>
4955
<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">
@@ -93,125 +99,137 @@ export default function Home() {
9399
<main className="mt-6 md:pb-4">
94100
<Prose>
95101
<h2>Posts</h2>
96-
{entries.map((entry, index) => {
97-
const rule = index < entries.length - 1 ? <hr /> : null
102+
<Suspense
103+
fallback={<div aria-label="Loading" className="loader pl-2" />}
104+
>
105+
<Await resolve={data.entries}>
106+
{(entries) =>
107+
entries.map((entry, index) => {
108+
const rule = index < entries.length - 1 ? <hr /> : null
109+
110+
if ('source' in entry) {
111+
if ('parts' in entry) {
112+
const externalSeries = entry
113+
return (
114+
<Fragment key={externalSeries.title}>
115+
<article>
116+
<h3>{externalSeries.title}</h3>
117+
<PostDate
118+
published={externalSeries.parts[0].published}
119+
/>
120+
<p>{externalSeries.description}</p>
121+
<p>Parts of this series:</p>
122+
<ol>
123+
{externalSeries.parts.map((part) => (
124+
<li key={part.title} className="space-x-2">
125+
<span className="dark:text-white">
126+
{part.title}
127+
</span>
128+
<span>·</span>
129+
<a
130+
href={part.url}
131+
target="_blank"
132+
rel="noreferrer"
133+
className="inline-flex items-center space-x-2"
134+
>
135+
<span>Read on {externalSeries.source}</span>
136+
<svg aria-hidden="true" className="h-6 w-6">
137+
<use href={`${spriteUrl}#external`} />
138+
</svg>
139+
</a>
140+
</li>
141+
))}
142+
</ol>
143+
</article>
144+
{rule}
145+
</Fragment>
146+
)
147+
}
98148

99-
if ('source' in entry) {
100-
if ('parts' in entry) {
101-
const externalSeries = entry
102-
return (
103-
<Fragment key={externalSeries.title}>
104-
<article>
105-
<h3>{externalSeries.title}</h3>
106-
<PostDate published={externalSeries.parts[0].published} />
107-
<p>{externalSeries.description}</p>
108-
<p>Parts of this series:</p>
109-
<ol>
110-
{externalSeries.parts.map((part) => (
111-
<li key={part.title} className="space-x-2">
112-
<span className="dark:text-white">
113-
{part.title}
114-
</span>
115-
<span>·</span>
149+
const externalPost = entry
150+
return (
151+
<Fragment key={externalPost.title}>
152+
<article>
153+
<h3>
154+
<a
155+
href={externalPost.url}
156+
target="_blank"
157+
rel="noreferrer"
158+
>
159+
{externalPost.title}
160+
</a>
161+
</h3>
162+
<PostDate published={externalPost.published} />
163+
<p>{externalPost.description}</p>
164+
<p>
116165
<a
117-
href={part.url}
166+
href={externalPost.url}
118167
target="_blank"
119168
rel="noreferrer"
120169
className="inline-flex items-center space-x-2"
121170
>
122-
<span>Read on {externalSeries.source}</span>
171+
<span>Read on {externalPost.source}</span>
123172
<svg aria-hidden="true" className="h-6 w-6">
124173
<use href={`${spriteUrl}#external`} />
125174
</svg>
126175
</a>
127-
</li>
128-
))}
129-
</ol>
130-
</article>
131-
{rule}
132-
</Fragment>
133-
)
134-
}
176+
</p>
177+
</article>
178+
{rule}
179+
</Fragment>
180+
)
181+
}
135182

136-
const externalPost = entry
137-
return (
138-
<Fragment key={externalPost.title}>
139-
<article>
140-
<h3>
141-
<a
142-
href={externalPost.url}
143-
target="_blank"
144-
rel="noreferrer"
145-
>
146-
{externalPost.title}
147-
</a>
148-
</h3>
149-
<PostDate published={externalPost.published} />
150-
<p>{externalPost.description}</p>
151-
<p>
152-
<a
153-
href={externalPost.url}
154-
target="_blank"
155-
rel="noreferrer"
156-
className="inline-flex items-center space-x-2"
157-
>
158-
<span>Read on {externalPost.source}</span>
159-
<svg aria-hidden="true" className="h-6 w-6">
160-
<use href={`${spriteUrl}#external`} />
161-
</svg>
162-
</a>
163-
</p>
164-
</article>
165-
{rule}
166-
</Fragment>
167-
)
168-
}
169-
170-
if ('parts' in entry) {
171-
const series = entry
172-
return (
173-
<Fragment key={series.slug}>
174-
<article>
175-
<h3>
176-
<Link to={`/blog/${series.slug}/${series.parts[0].slug}`}>
177-
{series.title}
178-
</Link>
179-
</h3>
180-
<PostDate published={series.published ?? undefined} />
181-
<p>{series.description}</p>
182-
<p>Parts of this series:</p>
183-
<ol>
184-
{series.parts.map((part) => (
185-
<li key={part.slug}>
186-
<Link to={`/blog/${series.slug}/${part.slug}`}>
187-
{part.title}
188-
</Link>
189-
</li>
190-
))}
191-
</ol>
192-
</article>
193-
{rule}
194-
</Fragment>
195-
)
196-
}
183+
if ('parts' in entry) {
184+
const series = entry
185+
return (
186+
<Fragment key={series.slug}>
187+
<article>
188+
<h3>
189+
<Link
190+
to={`/blog/${series.slug}/${series.parts[0].slug}`}
191+
>
192+
{series.title}
193+
</Link>
194+
</h3>
195+
<PostDate published={series.published ?? undefined} />
196+
<p>{series.description}</p>
197+
<p>Parts of this series:</p>
198+
<ol>
199+
{series.parts.map((part) => (
200+
<li key={part.slug}>
201+
<Link to={`/blog/${series.slug}/${part.slug}`}>
202+
{part.title}
203+
</Link>
204+
</li>
205+
))}
206+
</ol>
207+
</article>
208+
{rule}
209+
</Fragment>
210+
)
211+
}
197212

198-
const post = entry
199-
return (
200-
<Fragment key={post.slug}>
201-
<article>
202-
<h3>
203-
<Link to={`/blog/${post.slug}`}>{post.title}</Link>
204-
</h3>
205-
<PostDate published={post.published ?? undefined} />
206-
<p>{post.description}</p>
207-
<p>
208-
<Link to={`/blog/${post.slug}`}>Read more →</Link>
209-
</p>
210-
</article>
211-
{rule}
212-
</Fragment>
213-
)
214-
})}
213+
const post = entry
214+
return (
215+
<Fragment key={post.slug}>
216+
<article>
217+
<h3>
218+
<Link to={`/blog/${post.slug}`}>{post.title}</Link>
219+
</h3>
220+
<PostDate published={post.published ?? undefined} />
221+
<p>{post.description}</p>
222+
<p>
223+
<Link to={`/blog/${post.slug}`}>Read more →</Link>
224+
</p>
225+
</article>
226+
{rule}
227+
</Fragment>
228+
)
229+
})
230+
}
231+
</Await>
232+
</Suspense>
215233
</Prose>
216234
</main>
217235
</>

app/utils/posts.server.ts

+14-13
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@ import { basename, dirname, join as joinPath } from 'path'
33

44
const standalonePostFrontmatter = import.meta.glob<StandalonePostFrontmattter>(
55
'/posts/*.mdx',
6-
{ import: 'frontmatter', eager: true },
6+
{ import: 'frontmatter' },
77
)
88
const seriesPostFrontmatter = import.meta.glob<SeriesPostFrontmatter>(
99
'/posts/*/*.mdx',
10-
{ import: 'frontmatter', eager: true },
10+
{ import: 'frontmatter' },
1111
)
1212
const seriesMeta = import.meta.glob<SeriesMeta>('/posts/*/series.json', {
1313
import: 'default',
14-
eager: true,
1514
})
1615

1716
export interface StandalonePostFrontmattter {
@@ -127,7 +126,7 @@ export async function getAllPostsMeta() {
127126
...externalPosts,
128127
...Object.keys(standalonePostFrontmatter).map(async (path) => {
129128
const slug = basename(path, '.mdx')
130-
const meta = standalonePostFrontmatter[path]
129+
const meta = await standalonePostFrontmatter[path]()
131130
const result: StandalonePostFrontmattter & {
132131
slug: string
133132
fileModified?: string
@@ -174,11 +173,11 @@ export async function getAllPostsMeta() {
174173
})
175174
}
176175

177-
export function getStandalonePostMeta(slug: string) {
176+
export async function getStandalonePostMeta(slug: string) {
178177
const path = `/posts/${slug}.mdx`
179178
const isStandalonePost = path in standalonePostFrontmatter
180179
if (!isStandalonePost) return null
181-
const frontmatter = standalonePostFrontmatter[path]
180+
const frontmatter = await standalonePostFrontmatter[path]()
182181
const isPublished = 'published' in frontmatter
183182
if (!isPublished && !import.meta.env.DEV) return null
184183
return frontmatter
@@ -188,18 +187,20 @@ export async function getSeriesMeta(slug: string) {
188187
const seriesPath = `/posts/${slug}/series.json`
189188
const isSeries = seriesPath in seriesMeta
190189
if (!isSeries) return null
191-
const meta = seriesMeta[seriesPath]
190+
const meta = await seriesMeta[seriesPath]()
192191
const isPublished = 'published' in meta
193192
if (!isPublished && !import.meta.env.DEV) return null
194193
const partPaths = Object.keys(seriesPostFrontmatter).filter((postPath) =>
195194
postPath.startsWith(`/posts/${slug}/`),
196195
)
197-
const parts = partPaths
198-
.map((postPath) => ({
199-
slug: basename(postPath, '.mdx'),
200-
...seriesPostFrontmatter[postPath],
201-
}))
202-
.sort((a, b) => a.seriesPart - b.seriesPart)
196+
const parts = await Promise.all(
197+
partPaths.map(async (postPath) => {
198+
const meta = await seriesPostFrontmatter[postPath]()
199+
return { slug: basename(postPath, '.mdx'), ...meta }
200+
}),
201+
).then((parts) => {
202+
return parts.sort((a, b) => a.seriesPart - b.seriesPart)
203+
})
203204

204205
const result: SeriesMeta & {
205206
slug: string

0 commit comments

Comments
 (0)