Skip to content

Commit

Permalink
Remove date-fns dependency and reduce bundle size (#163)
Browse files Browse the repository at this point in the history
* chore: uninstall date-fns

* feat: create utils to format date using Intl.DateTimeFormat

* feat: replace date-fns/fomat with new formatDate utils

* chore: move type definition to the top of the file

* Don't create a new object on every iteration

* Make the date a server component

---------

Co-authored-by: Luis Alvarez <luis@vercel.com>
  • Loading branch information
jahirfiquitiva and lfades committed Apr 8, 2024
1 parent a292ca7 commit f6d34db
Show file tree
Hide file tree
Showing 6 changed files with 2,727 additions and 3,003 deletions.
1 change: 0 additions & 1 deletion apps/next-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"@next/mdx": "^14.0.4",
"@vercel/kv": "^1.0.1",
"clsx": "^2.0.0",
"date-fns": "^2.30.0",
"next": "14.0.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@
"prettier": "^2.8.4",
"turbo": "^1.8.3"
},
"packageManager": "pnpm@7.15.0"
"packageManager": "pnpm@8.14.3"
}
1 change: 0 additions & 1 deletion packages/react-tweet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
"dependencies": {
"@swc/helpers": "^0.5.3",
"clsx": "^2.0.0",
"date-fns": "^2.30.0",
"swr": "^2.2.4"
},
"devDependencies": {
Expand Down
32 changes: 32 additions & 0 deletions packages/react-tweet/src/date-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
type PartsObject = Record<keyof Intl.DateTimeFormatPartTypesRegistry, string>

const options: Intl.DateTimeFormatOptions = {
hour: 'numeric',
minute: '2-digit',
hour12: true,
weekday: 'short',
month: 'short',
day: 'numeric',
year: 'numeric',
}

const formatter = new Intl.DateTimeFormat('en-US', options)

const partsArrayToObject = (
parts: ReturnType<typeof formatter.formatToParts>
): PartsObject => {
const result = {} as PartsObject

for (const part of parts) {
result[part.type] = part.value
}

return result
}

export const formatDate = (date: Date) => {
const parts = partsArrayToObject(formatter.formatToParts(date))
const formattedTime = `${parts.hour}:${parts.minute} ${parts.dayPeriod}`
const formattedDate = `${parts.month} ${parts.day}, ${parts.year}`
return `${formattedTime} · ${formattedDate}`
}
21 changes: 6 additions & 15 deletions packages/react-tweet/src/twitter-theme/tweet-info-created-at.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,20 @@
'use client'

import format from 'date-fns/format/index.js'
import type { EnrichedTweet } from '../utils.js'
import { useMounted } from '../hooks.js'
import { formatDate } from '../date-utils.js'
import s from './tweet-info-created-at.module.css'

export const TweetInfoCreatedAt = ({ tweet }: { tweet: EnrichedTweet }) => {
const mounted = useMounted()
// If the date is displayed immediately, it will produce a server/client mismatch because the date
// format will change depending on the user's browser. If the format were to be simplified to
// something like "MMM d, y", then you could use the server date.
const createdAt =
typeof window !== 'undefined' && mounted ? new Date(tweet.created_at) : null
const createdAt = new Date(tweet.created_at)
const formattedCreatedAtDate = formatDate(createdAt)

return !createdAt ? null : (
return (
<a
className={s.root}
href={tweet.url}
target="_blank"
rel="noopener noreferrer"
aria-label={format(createdAt, 'h:mm a · MMM d, y')}
aria-label={formattedCreatedAtDate}
>
<time dateTime={createdAt.toISOString()}>
{format(createdAt, 'h:mm a · MMM d, y')}
</time>
<time dateTime={createdAt.toISOString()}>{formattedCreatedAtDate}</time>
</a>
)
}

0 comments on commit f6d34db

Please sign in to comment.