1
- import { useLoaderData , Link , useRouteError } from '@remix-run/react'
1
+ import { useLoaderData , Link , useRouteError , Await } from '@remix-run/react'
2
2
import type {
3
3
MetaFunction ,
4
4
LoaderFunctionArgs ,
5
5
HeadersFunction ,
6
6
} 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'
9
9
import PostDate from '~/components/PostDate'
10
10
import ProfilePhoto from '~/components/ProfilePhoto'
11
11
import Prose from '~/components/Prose'
@@ -16,9 +16,15 @@ import circuitBoard from '~/images/circuit-board.svg'
16
16
import spriteUrl from '~/sprite.svg'
17
17
import clsx from 'clsx'
18
18
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
+ )
22
28
}
23
29
24
30
export const headers : HeadersFunction = ( { loaderHeaders } ) => {
@@ -43,7 +49,7 @@ export const meta: MetaFunction = () => {
43
49
}
44
50
45
51
export default function Home ( ) {
46
- const { entries } = useLoaderData < typeof loader > ( )
52
+ const data = useLoaderData < typeof loader > ( )
47
53
return (
48
54
< >
49
55
< 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() {
93
99
< main className = "mt-6 md:pb-4" >
94
100
< Prose >
95
101
< 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
+ }
98
148
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 >
116
165
< a
117
- href = { part . url }
166
+ href = { externalPost . url }
118
167
target = "_blank"
119
168
rel = "noreferrer"
120
169
className = "inline-flex items-center space-x-2"
121
170
>
122
- < span > Read on { externalSeries . source } </ span >
171
+ < span > Read on { externalPost . source } </ span >
123
172
< svg aria-hidden = "true" className = "h-6 w-6" >
124
173
< use href = { `${ spriteUrl } #external` } />
125
174
</ svg >
126
175
</ a >
127
- </ li >
128
- ) ) }
129
- </ ol >
130
- </ article >
131
- { rule }
132
- </ Fragment >
133
- )
134
- }
176
+ </ p >
177
+ </ article >
178
+ { rule }
179
+ </ Fragment >
180
+ )
181
+ }
135
182
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
+ }
197
212
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 >
215
233
</ Prose >
216
234
</ main >
217
235
</ >
0 commit comments