Skip to content

Commit 68dfe5f

Browse files
committed
refactor: convert dynamic imports to static imports
- Move blog post loading to createServerFn (loadBlogPost) - Static imports work when server code is in createServerFn - Route loaders that directly import server modules need dynamic imports - setCacheHeaders can be static in routes using createServerFn
1 parent fc8b892 commit 68dfe5f

File tree

4 files changed

+54
-44
lines changed

4 files changed

+54
-44
lines changed

src/routes/blog.$.tsx

Lines changed: 7 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { notFound, redirect, createFileRoute } from '@tanstack/react-router'
22
import { seo } from '~/utils/seo'
33
import { PostNotFound } from './blog'
44
import { formatAuthors } from '~/utils/blog'
5-
import { format } from '~/utils/dates'
65
import { allPosts } from 'content-collections'
76
import * as React from 'react'
87
import { GamHeader } from '~/components/Gam'
@@ -13,6 +12,7 @@ import { DocTitle } from '~/components/DocTitle'
1312
import { CopyPageDropdown } from '~/components/CopyPageDropdown'
1413
import { Button } from '~/ui'
1514
import { SquarePen } from 'lucide-react'
15+
import { loadBlogPost } from '~/utils/renderBlogContent'
1616

1717
function handleRedirects(docsPath: string) {
1818
if (docsPath.includes('directives-the-new-framework-lock-in')) {
@@ -25,50 +25,20 @@ function handleRedirects(docsPath: string) {
2525
export const Route = createFileRoute('/blog/$')({
2626
staleTime: Infinity,
2727
loader: async ({ params }) => {
28-
const docsPath = params._splat
29-
if (!docsPath) {
28+
const slug = params._splat
29+
if (!slug) {
3030
throw new Error('Invalid docs path')
3131
}
3232

33-
handleRedirects(docsPath)
34-
35-
const filePath = `src/blog/${docsPath}.md`
36-
const post = allPosts.find((p) => p.slug === docsPath)
33+
handleRedirects(slug)
3734

35+
// Check if post exists before calling server function
36+
const post = allPosts.find((p) => p.slug === slug)
3837
if (!post) {
3938
throw notFound()
4039
}
4140

42-
const { setCacheHeaders } = await import('~/utils/headers.server')
43-
setCacheHeaders()
44-
45-
const now = new Date()
46-
const publishDate = new Date(post.published)
47-
const isUnpublished = post.draft || publishDate > now
48-
49-
const blogContent = `<small>_by ${formatAuthors(post.authors)} on ${format(
50-
new Date(post.published || 0),
51-
'MMMM d, yyyy',
52-
)}._</small>
53-
54-
${post.content}`
55-
56-
const { renderMarkdownToJsx } = await import('~/utils/markdown')
57-
const { headings } = await renderMarkdownToJsx(blogContent)
58-
const { renderBlogContent } = await import('~/utils/renderBlogContent')
59-
const ContentRsc = await renderBlogContent({ data: blogContent })
60-
61-
return {
62-
title: post.title,
63-
description: post.description,
64-
published: post.published,
65-
authors: post.authors,
66-
headerImage: post.headerImage,
67-
filePath,
68-
isUnpublished,
69-
headings,
70-
ContentRsc,
71-
}
41+
return loadBlogPost({ data: { slug } })
7242
},
7343
head: ({ loaderData }) => {
7444
// Generate optimized social media image URL using Netlify Image CDN

src/routes/blog.index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { Footer } from '~/components/Footer'
88
import { PostNotFound } from './blog'
99
import { createServerFn } from '@tanstack/react-start'
1010
import { RssIcon } from 'lucide-react'
11+
import { setCacheHeaders } from '~/utils/headers.server'
1112

1213
type BlogFrontMatter = {
1314
slug: string
@@ -19,7 +20,6 @@ type BlogFrontMatter = {
1920

2021
const fetchFrontMatters = createServerFn({ method: 'GET' }).handler(
2122
async () => {
22-
const { setCacheHeaders } = await import('~/utils/headers.server')
2323
setCacheHeaders()
2424

2525
const posts = getPublishedPosts()

src/routes/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { formatAuthors, getPublishedPosts } from '~/utils/blog'
1919
import { format } from '~/utils/dates'
2020
import { SimpleMarkdown } from '~/components/SimpleMarkdown'
2121
import { renderMarkdownAsync } from '~/utils/markdown'
22+
import { setCacheHeaders } from '~/utils/headers.server'
2223
import { NetlifyImage } from '~/components/NetlifyImage'
2324
import { createServerFn } from '@tanstack/react-start'
2425
import { AdGate } from '~/contexts/AdsContext'
@@ -63,7 +64,6 @@ type BlogFrontMatter = {
6364

6465
const fetchRecentPosts = createServerFn({ method: 'GET' }).handler(
6566
async (): Promise<BlogFrontMatter[]> => {
66-
const { setCacheHeaders } = await import('~/utils/headers.server')
6767
setCacheHeaders()
6868

6969
const posts = getPublishedPosts().slice(0, 3)

src/utils/renderBlogContent.tsx

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,50 @@ import { createServerFn } from '@tanstack/react-start'
66
import { renderServerComponent } from '@tanstack/react-start/rsc'
77
import { renderMarkdownToJsx } from '~/utils/markdown'
88
import { BlogContent } from '~/components/markdown/BlogContent'
9+
import { setCacheHeaders } from '~/utils/headers.server'
10+
import { allPosts } from 'content-collections'
11+
import { formatAuthors } from '~/utils/blog'
12+
import { format } from '~/utils/dates'
13+
import { notFound } from '@tanstack/react-router'
14+
import * as v from 'valibot'
915

10-
export const renderBlogContent = createServerFn({ method: 'GET' })
11-
.inputValidator((content: string) => content)
12-
.handler(async ({ data: content }) => {
13-
const { content: jsxContent } = await renderMarkdownToJsx(content)
14-
return renderServerComponent(<BlogContent>{jsxContent}</BlogContent>)
16+
export const loadBlogPost = createServerFn({ method: 'GET' })
17+
.inputValidator(v.object({ slug: v.string() }))
18+
.handler(async ({ data: { slug } }) => {
19+
const post = allPosts.find((p) => p.slug === slug)
20+
21+
if (!post) {
22+
throw notFound()
23+
}
24+
25+
setCacheHeaders()
26+
27+
const now = new Date()
28+
const publishDate = new Date(post.published)
29+
const isUnpublished = post.draft || publishDate > now
30+
31+
const blogContent = `<small>_by ${formatAuthors(post.authors)} on ${format(
32+
new Date(post.published || 0),
33+
'MMMM d, yyyy',
34+
)}._</small>
35+
36+
${post.content}`
37+
38+
const { content: jsxContent, headings } =
39+
await renderMarkdownToJsx(blogContent)
40+
const ContentRsc = await renderServerComponent(
41+
<BlogContent>{jsxContent}</BlogContent>,
42+
)
43+
44+
return {
45+
title: post.title,
46+
description: post.description,
47+
published: post.published,
48+
authors: post.authors,
49+
headerImage: post.headerImage,
50+
filePath: `src/blog/${slug}.md`,
51+
isUnpublished,
52+
headings,
53+
ContentRsc,
54+
}
1555
})

0 commit comments

Comments
 (0)