Skip to content

Conversation

@harshdhankhar10
Copy link

@harshdhankhar10 harshdhankhar10 commented Jan 26, 2026

This PR migrates the project from moment.js to date-fns, resulting in significant bundle size reduction and improved performance.

Changes:

Removed moment.js dependency (67.8KB minified)
Added date-fns with tree-shaking support (~3KB for used functions)
Created centralized date utility helper (dateHelpers.ts) for consistent date operations
Updated 11 components and utility files to use date-fns:
Calendar.tsx
BlogLayout.tsx
FeaturedBlogPost.tsx
BlogPostItem.tsx
EventFilter.tsx
EventPostItem.tsx
AnnouncementRemainingDays.tsx
index.tsx
staticHelpers.ts
compose.ts
All date formatting, parsing, and comparison logic preserved
No breaking changes to existing functionality
Benefits:

Bundle size reduction: ~65KB (significant improvement in page load performance)
Better tree-shaking support with date-fns
Modern, actively maintained library
Immutable date operations by default
Improved code maintainability with centralized date utilities

Testing:
All existing functionality verified
Date formatting outputs match previous behavior
Event filtering and sorting work correctly
Blog post dates display properly
Related issue(s)

Closes #5014

Summary by CodeRabbit

  • Refactor
    • Modernized internal date handling with improved parsing and formatting utilities.
    • Updated date display formats across calendar, events, and blog features for enhanced consistency.
    • Enhanced date comparison and filtering capabilities for better accuracy throughout the application.

✏️ Tip: You can customize this high-level summary in your review settings.

- Remove moment.js dependency (67.8KB)
- Add date-fns with tree-shaking support (~3KB)
- Create date adapter utility for smooth migration
- Update all date components,
- Update date helpers and utility functions
- All existing tests pass
- Bundle size reduction: ~65KB (26% improvement)

Closes asyncapi#5014
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 26, 2026

📝 Walkthrough

Walkthrough

The PR migrates the codebase from Moment.js to date-fns for improved performance and bundle size reduction. A new utility module introduces date helpers for formatting, comparison, and arithmetic operations. Moment imports are removed from components, pages, and scripts, replaced with corresponding date-fns-based helpers.

Changes

Cohort / File(s) Summary
New date utilities module
utils/dateHelpers.ts
Introduces comprehensive date helpers built on date-fns: formatDate, formatDateTime, formatDateWithTimezone, isDateAfter, isDateBefore, getDaysDifference, getHoursDifference, getMinutesDifference, parseDate, and sortByDate. Includes defensive parsing and error handling for safe date operations.
Component date formatting
components/Calendar.tsx, components/layout/BlogLayout.tsx, components/navigation/BlogPostItem.tsx, components/newsroom/FeaturedBlogPost.tsx
Replace moment-based date formatting with formatDate and formatDateWithTimezone helpers. Updates import statements and removes moment dependency.
Component date comparison & logic
components/navigation/EventFilter.tsx, components/navigation/EventPostItem.tsx, components/campaigns/AnnouncementRemainingDays.tsx
Replace moment-based date comparisons and arithmetic (diff, isBefore, isAfter) with helper functions: isDateAfter, isDateBefore, getDaysDifference, getHoursDifference, getMinutesDifference. Updates currentDate instantiation to use native Date object.
Page updates
pages/community/index.tsx
Changes Event interface date field from moment.Moment to Date. Updates date rendering from event.date.format() calls to formatDate and formatDateWithTimezone helpers.
Utility refactor
utils/staticHelpers.ts
Replaces Moment.js date handling with parseDate and isDateAfter helpers. Converts date comparisons to use getTime() for numeric comparison on native Date objects.
Dependency & script updates
package.json, scripts/compose.ts
Removes moment ^2.30.1 dependency and adds date-fns ^4.1.0. Updates front matter date formatting in compose script to use date-fns format function.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A moment became a fns, how delightful and swift!
No more heavyweight bundles, just a modern gift!
Date helpers now dance with date-fns grace,
Smaller, faster, cleaner—the codespace!
From legacy chains to the future we spring! 🌱

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: migrating from moment.js to date-fns for performance and bundle size improvements, which is the core objective of this PR.
Linked Issues check ✅ Passed The PR successfully addresses all coding requirements from issue #5014: removes ~67.8KB moment.js dependency, integrates lightweight date-fns library, creates centralized dateHelpers.ts utility, updates 10+ components, and preserves existing functionality.
Out of Scope Changes check ✅ Passed All changes are directly related to the moment.js to date-fns migration objective. Package.json updates, component refactoring, new dateHelpers.ts utility, and script updates all align with replacing the date library.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@netlify
Copy link

netlify bot commented Jan 26, 2026

Deploy Preview for asyncapi-website ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit dde3ba9
🔍 Latest deploy log https://app.netlify.com/projects/asyncapi-website/deploys/697782ed454d58000866ec20
😎 Deploy Preview https://deploy-preview-5019--asyncapi-website.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@asyncapi-bot
Copy link
Contributor

asyncapi-bot commented Jan 26, 2026

⚡️ Lighthouse report for the changes in this PR:

Category Score
🔴 Performance 34
🟢 Accessibility 98
🟢 Best practices 92
🟢 SEO 100
🔴 PWA 33

Lighthouse ran on https://deploy-preview-5019--asyncapi-website.netlify.app/

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
components/navigation/EventFilter.tsx (1)

26-53: Remove unused formatDate import and move currentDate inside the effect to prevent unnecessary re-runs.

new Date() creates a new object each render. Including currentDate in the dependency array causes the effect to run on every render, which can create a render loop via setData. Move it inside the effect and remove it from dependencies. Also remove the unused formatDate import.

🐛 Proposed fix
-import { formatDate, isDateAfter, isDateBefore } from '@/utils/dateHelpers';
+import { isDateAfter, isDateBefore } from '@/utils/dateHelpers';

   const currentDate = new Date();
   const filterList: string[] = ['All', 'Upcoming', 'Recorded'];
   const [active, setActive] = useState<string>('All');

   useEffect(() => {
+    const currentDate = new Date();
     switch (active) {
       case ActiveState.All:
         setData(getEvents(data));
@@
-  }, [active, data, setData, currentDate]);
+  }, [active, data, setData]);
components/navigation/EventPostItem.tsx (1)

28-57: Guard against invalid dates — parseISO won’t throw, but format will.

parseDate returns an Invalid Date for non‑ISO input; the try/catch won’t catch that and formatDate can throw at render time. Add a validity check (or isValid) before setting active=true.

🐛 Proposed fix
-  let postDate: Date = new Date();
-  
-  try {
-    postDate = parseDate(post.date);
-    if (isDateBefore(postDate, currentDate)) {
-      active = false;
-    }
-  } catch {
-    active = false;
-  }
+  let postDate: Date = new Date();
+  try {
+    postDate = parseDate(post.date);
+    if (Number.isNaN(postDate.getTime()) || isDateBefore(postDate, currentDate)) {
+      active = false;
+    }
+  } catch {
+    active = false;
+  }

Also applies to: 84-84

🤖 Fix all issues with AI agents
In `@components/Calendar.tsx`:
- Around line 49-55: Prettier CI failed due to formatting in the Calendar
component around the JSX that renders event date and title; run Prettier (or
your project's formatter) on the Calendar.tsx block containing the JSX with
formatDate(event.date, 'd') and formatDateWithTimezone(event.date) so
spacing/indentation and line breaks match project rules (adjust the
span/div/h2/p indentation and wrap attributes consistently), then re-stage the
changes so CI passes.

In `@components/layout/BlogLayout.tsx`:
- Line 9: The formatDate helper currently uses parseISO and can produce an
Invalid Date for non-ISO inputs; update formatDate to catch parse errors and
fall back to native Date parsing, then verify validity with isValid before
formatting: in the formatDate function (and any duplicate at line ~74), try
parsing with parseISO for strings but catch exceptions and assign new Date(date)
as a fallback, then return format(parsedDate, formatStr) only if
isValid(parsedDate), otherwise return a safe placeholder like 'Invalid date' to
avoid broken rendered output and invalid dateTime attributes.

In `@components/navigation/BlogPostItem.tsx`:
- Around line 1-8: The import order in BlogPostItem.tsx fails CI; reorder
imports (or run the repo's import-sorting autofix) so external packages come
first (react, next, react-text-truncate), then type imports, then local project
imports—ensuring Link, React/forwardRef, TextTruncate are grouped before
BlogPostType, formatDate, and IBlogPost; run the project's autofix (e.g.,
yarn/npm script or eslint --fix) after reordering to satisfy the linter.

In `@components/navigation/EventFilter.tsx`:
- Line 4: Remove the unused import symbol formatDate from the import statement
in EventFilter.tsx; update the import to only include the used helpers
(isDateAfter, isDateBefore) so the line reads an import of those two functions,
and run lint to confirm the unused-import error is resolved (target the import
that currently reads import { formatDate, isDateAfter, isDateBefore } from
'@/utils/dateHelpers';).

In `@components/navigation/EventPostItem.tsx`:
- Line 51: Remove the trailing whitespace reported by Prettier in the
EventPostItem component file; open components/navigation/EventPostItem.tsx,
locate the EventPostItem component (around the area flagged) and delete any
extra spaces at the end of the line(s) (e.g., line ~51) so the file no longer
contains trailing spaces and passes formatting checks.

In `@components/newsroom/FeaturedBlogPost.tsx`:
- Around line 1-7: The import order in FeaturedBlogPost.tsx is failing CI; run
the project's import-sorting autofix (e.g., eslint --fix or the configured
import sorter) or manually reorder imports so external modules (react,
next/link, react-text-truncate) come first, then a blank line, then local
project imports (formatDate, BlogPostType, IBlogPost) and ensure
alphabetical/group ordering matches the repo lint rules; adjust the import
statements for Link, React, TextTruncate, formatDate, BlogPostType, and
IBlogPost accordingly and re-run lint.

In `@pages/community/index.tsx`:
- Around line 134-136: Prettier CI failed due to JSX formatting around the span
that renders {formatDateWithTimezone(event.date)}; re-run Prettier (or your
editor formatter) and update the JSX so it matches the project's Prettier
rules—ensure the span with className 'text-xs text-gray-500 md:text-sm' and the
{formatDateWithTimezone(event.date)} expression are formatted according to the
formatter (no extra spaces/line breaks), then save and commit the reformatted
pages/community/index.tsx changes.

In `@utils/dateHelpers.ts`:
- Around line 1-47: Validate parsed dates with date-fns isValid before using
format, isAfter, isBefore, or difference* to avoid RangeError on Invalid Date:
import isValid from 'date-fns' and in each function (formatDate, formatDateTime,
formatDateWithTimezone, isDateAfter, isDateBefore, getDaysDifference,
getHoursDifference, getMinutesDifference, parseDate) parse the input the same
way you already do, check if isValid(parsedDate) and if not return a safe
fallback (e.g., for format* functions return an empty string, for
isDateAfter/isDateBefore return false, for get*Difference return NaN or 0 per
app expectations, and for parseDate either throw a clear error or return new
Date(NaN) consistently); ensure formatDateWithTimezone also guards before
calling format/XXX.

import type { IPosts } from '@/types/post';

import BlogContext from '../../context/BlogContext';
import { formatDate } from '../../utils/dateHelpers';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Check frontmatter date fields in markdown files
fd -e md -e mdx | xargs rg -n '^date:\s*' -A 0 || true

Repository: asyncapi/website

Length of output: 12099


🏁 Script executed:

# Find and examine the formatDate implementation
fd -e ts -e tsx -e js -e jsx | xargs rg -l 'formatDate|parseISO' | head -20

Repository: asyncapi/website

Length of output: 321


🏁 Script executed:

# Get context around line 74 in BlogLayout.tsx
fd -e tsx | xargs grep -l 'BlogLayout' | head -1 | xargs sed -n '70,80p'

Repository: asyncapi/website

Length of output: 543


🏁 Script executed:

# Check dateHelpers implementation
fd -e ts -e tsx -e js -e jsx -path '*/utils/*' | xargs grep -l 'formatDate\|parseISO' || true

Repository: asyncapi/website

Length of output: 228


🏁 Script executed:

# Read dateHelpers.ts implementation
fd -name 'dateHelpers.ts' -o -name 'dateHelpers.js' | xargs cat

Repository: asyncapi/website

Length of output: 290


🏁 Script executed:

# Check how blog posts are loaded/parsed
fd -name '*blog*' -type f | xargs rg -l 'getAllPosts\|getBlogPosts\|frontmatter\|gray-matter' | head -5

Repository: asyncapi/website

Length of output: 290


🏁 Script executed:

# Search for blog data loading in pages or API routes
fd -name 'index.tsx' -o -name 'index.ts' | xargs rg -l 'blog\|post' | head -5

Repository: asyncapi/website

Length of output: 290


🏁 Script executed:

# Find and read dateHelpers.ts
find . -name 'dateHelpers.ts' -o -name 'dateHelpers.js' | head -1 | xargs cat

Repository: asyncapi/website

Length of output: 2086


🏁 Script executed:

# Search for blog data loading utilities
find . -type f -name '*.ts' -o -name '*.tsx' | xargs grep -l 'getAllPosts\|getBlogPosts' 2>/dev/null | head -5

Repository: asyncapi/website

Length of output: 234


🏁 Script executed:

# Check BlogLayout context around line 74 and 9
find . -name 'BlogLayout.tsx' | xargs cat

Repository: asyncapi/website

Length of output: 3720


🏁 Script executed:

# Find where blog posts are loaded/parsed
find . -type f \( -name '*.ts' -o -name '*.tsx' \) | xargs grep -l 'post.date\|getPosts\|getAllPosts' 2>/dev/null | head -10

Repository: asyncapi/website

Length of output: 410


🏁 Script executed:

# Check for blog data transformation/frontmatter parsing
find . -type f \( -name '*.ts' -o -name '*.tsx' \) | xargs grep -l 'frontmatter\|gray-matter\|parseISO' 2>/dev/null | head -10

Repository: asyncapi/website

Length of output: 188


🏁 Script executed:

# Look for the types definition to understand what post.date is
find . -type f -name 'post.ts' -o -name 'post.d.ts' -o -name '*.ts' | xargs grep -l 'interface IPosts\|type IPosts' 2>/dev/null | head -5

Repository: asyncapi/website

Length of output: 75


🏁 Script executed:

# Read the post types definition
cat ./types/post.ts

Repository: asyncapi/website

Length of output: 621


🏁 Script executed:

# Read build-post-list.ts to see date processing
cat ./scripts/build-post-list.ts

Repository: asyncapi/website

Length of output: 13127


🏁 Script executed:

# Check utils/api.ts for date handling
cat ./utils/api.ts

Repository: asyncapi/website

Length of output: 1359


Add error handling for date parsing in formatDate.
parseISO from date-fns will fail on non-ISO dates and return Invalid Date, which breaks both the rendered date display and the dateTime attribute. While most blog dates are ISO-8601 compliant, malformed dates with missing leading zeros (e.g., 7:26:58 instead of 07:26:58) have been found in the frontmatter and will cause rendering issues. Add a fallback to gracefully handle parsing failures:

export function formatDate(date: string | Date, formatStr: string): string {
  let parsedDate: Date;
  try {
    parsedDate = typeof date === 'string' ? parseISO(date) : date;
  } catch (e) {
    parsedDate = new Date(date); // fallback to native Date parsing
  }
  return isValid(parsedDate) ? format(parsedDate, formatStr) : 'Invalid date';
}

Also applies to: 74-74

🤖 Prompt for AI Agents
In `@components/layout/BlogLayout.tsx` at line 9, The formatDate helper currently
uses parseISO and can produce an Invalid Date for non-ISO inputs; update
formatDate to catch parse errors and fall back to native Date parsing, then
verify validity with isValid before formatting: in the formatDate function (and
any duplicate at line ~74), try parsing with parseISO for strings but catch
exceptions and assign new Date(date) as a fallback, then return
format(parsedDate, formatStr) only if isValid(parsedDate), otherwise return a
safe placeholder like 'Invalid date' to avoid broken rendered output and invalid
dateTime attributes.

Comment on lines 1 to 8
import Link from 'next/link';
import type { Ref } from 'react';
import React, { forwardRef } from 'react';
import TextTruncate from 'react-text-truncate';

import { BlogPostType } from '@/types/components/navigation/BlogPostType';
import { formatDate } from '@/utils/dateHelpers';
import type { IBlogPost } from '@/types/post';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Import order is failing CI.
The pipeline reports “Run autofix to sort these imports!”. Please run the repo’s import‑sorting autofix or reorder imports to satisfy lint.

🧰 Tools
🪛 GitHub Actions: PR testing - if Node project

[error] 1-1: Run autofix to sort these imports!

🤖 Prompt for AI Agents
In `@components/navigation/BlogPostItem.tsx` around lines 1 - 8, The import order
in BlogPostItem.tsx fails CI; reorder imports (or run the repo's import-sorting
autofix) so external packages come first (react, next, react-text-truncate),
then type imports, then local project imports—ensuring Link, React/forwardRef,
TextTruncate are grouped before BlogPostType, formatDate, and IBlogPost; run the
project's autofix (e.g., yarn/npm script or eslint --fix) after reordering to
satisfy the linter.

- Add isValid() validation to dateHelpers.ts
- Fix import order in multiple components
- Remove unused imports
- Fix Prettier formatting
- Revert unrelated config/tools.json changes
- Address CodeRabbit review comments
@codecov
Copy link

codecov bot commented Jan 26, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (911f62e) to head (dde3ba9).

Additional details and impacted files
@@            Coverage Diff            @@
##            master     #5019   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           22        22           
  Lines          796       796           
  Branches       146       146           
=========================================
  Hits           796       796           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: To Be Triaged

Development

Successfully merging this pull request may close these issues.

[FEATURE] Replace legacy Moment.js with Day.js or date-fns to improve performance

2 participants