Migrate Moment.js sang Day.js - developer documentation and reference notes for Migrate Moment.js sang Day.js.
Migrate Moment.js sang Day.js
1. Learning Objectives
By the end of this article, you'll be able to:
- Giảm bundle size hơn 97% bằng cách thay thế
moment.js(~230KB) bằngdayjs(~2KB minified + gzipped). - Chuyển đổi cú pháp song song giữa Moment.js và Day.js cho tất cả các thao tác thường gặp (parse, format, add/subtract, diff, timezone).
- Kích hoạt các Day.js plugins (
customParseFormat,utc,timezone,relativeTime,isBetween) để tái lập 100% tính năng của Moment.js. - Xử lý triệt để phụ thuộc Moment.js trong các plugin UI legacy như
bootstrap-daterangepicker.
2. Plan Availability & Prerequisites
Kỹ thuật migration này áp dụng cho mọi dự án JavaScript frontend/backend (Vue.js, React, Node.js, Webpack, Vite, hoặc AEM Clientlibs).
Day.js được thiết kế với API tương thích gần như 1:1 với Moment.js. Nếu bạn đã quen thuộc với Moment.js, bạn sẽ không cần phải học lại cú pháp mới.
3. What Is Day.js? — Definition & Expansion
Day.js là thư viện JavaScript xử lý ngày tháng bất biến (immutable), dung lượng siêu nhẹ (2KB) với API tương thích 1:1 với Moment.js.
Trong nhiều năm, Moment.js là chuẩn mực cho xử lý date/time trên web. Tuy nhiên, kiến trúc ban đầu của Moment.js mắc 2 hạn chế lớn trong phát triển web hiện đại:
- Dung lượng quá lớn: Moment chứa sẵn toàn bộ locale và không hỗ trợ Tree-shaking.
- Mutable State: Thực hiện
.add()hay.subtract()trên một instance sẽ làm thay đổi trực tiếp Date object ban đầu, dẫn đến vô số bug ẩn khó phát hiện.
Nhưng Day.js không chỉ dừng lại ở việc thay thế format ngày tháng cơ bản — bạn còn có thể dùng nó để chuyển đổi Timezone phức tạp, tính toán khoảng thời gian tương đối (relative time), và làm cầu nối (shim) cho các UI plugin legacy.
4. Types / Variants — Architecture Comparison
Mutable Architecture (Moment.js)
Mọi phương thức biến đổi trong Moment.js đều làm thay đổi (mutate) chính đối tượng hiện tại. Bạn buộc phải gọi .clone() nếu muốn giữ lại giá trị ban đầu.
Immutable Architecture (Day.js)
Mọi thao tác trên Day.js đều trả về một instance mới hoàn toàn. Instance ban đầu giữ nguyên giá trị, đảm bảo tính toàn vẹn dữ liệu trong Vuex/Redux store và pure functions.
5. How to Enable / Activate (Installation & Plugin Setup)
Day.js sử dụng kiến trúc Plugin-based. Core library chỉ chứa các hàm cơ bản (2KB). Muốn dùng tính năng nâng cao của Moment, bạn chỉ cần nạp plugin tương ứng.
Step 1: Cài đặt package
Step 2: Kích hoạt Plugins cần thiết
6. Using It in Practice — Side-by-Side Comparison
Dưới đây là bảng so sánh cú pháp 1:1 giữa Moment.js và Day.js cho các tác vụ lập trình hàng ngày.
6.1 Parse & Format Ngày Tháng
6.2 Cộng / Trừ & Đầu / Cuối Khoảng Thời Gian
6.3 So Sánh & Tính Khoảng Cách (Diff, IsBetween)
6.4 UTC, Timezone & Relative Time
7. Standout Feature: Handling daterangepicker Plugin
Một thách thức lớn khi refactor dự án legacy (đặc biệt các dự án AEM hoặc jQuery/Bootstrap) là plugin daterangepicker (như bootstrap-daterangepicker). Thư viện này phụ thuộc cứng vào window.moment.
Dưới đây là 3 chiến lược xử lý triệt để:
Chiến lược 1: Shim / Webpack Alias + badMutable (Giải pháp Re-architecture)
Nếu dự án dùng Webpack/Vite và bạn không muốn sửa lại code khởi tạo daterangepicker, bạn có thể dùng plugin badMutable của Day.js để biến Day.js thành mutable (giống Moment) và alias moment sang dayjs.
Trong file cấu hình Webpack:
Chiến lược 2: Adapter Pattern cho DateRangePicker Input
Nếu dự án không dùng Webpack Alias, bạn tạo Adapter chuyển đổi giữa Day.js object và native Date object / String format mà daterangepicker chấp nhận:
Chiến lược 3: Thay thế daterangepicker bằng Thư viện Modern Không Phụ Thuộc Moment
Về lâu dài, cách sạch nhất là thay thế bootstrap-daterangepicker bằng giải pháp hiện đại không phụ thuộc Moment.js:
Khi dùng badMutable shim window.moment, chỉ áp dụng cho phạm vi plugin legacy như daterangepicker. Trong code ứng dụng mới viết, luôn khuyến khích dùng Day.js chuẩn (immutable) để tránh lỗi sai lệch trạng thái date.
8. Security & Privacy Considerations
- Immutability ngăn ngừa Data Loss & Prototype Pollution: Việc dùng Day.js immutable tránh việc các hàm tiện ích vô tình chỉnh sửa đối tượng Date được dùng chung ở global state (Vuex/Pinia/Redux).
- Validate Input Strict: Khi nhận chuỗi ngày tháng từ người dùng hoặc API bên ngoài, luôn dùng
customParseFormatđể parse kèm format cụ thể thay vì parse tự do, tránh lỗi lệch múi giờ hoặc format sai. - Tránh Memory Leak trong Single Page Apps: Khi lặp lại các thao tác tính toán ngày tháng trong watcher hoặc render loop, các instance Day.js nhẹ (2KB) tạo ra ít áp lực cho Garbage Collector hơn rất nhiều so với Moment.js.
9. Creating Custom Migration Adapters (No Code Rewrite Required)
Để migrate một dự án lớn chứa hàng trăm file đang gọi moment(...) mà không phải sửa lại từng dòng code, bạn có thể tạo một Custom Helper Module đóng vai trò Facade:
Khi đó, trong các file component cũ, bạn chỉ cần thay đổi dòng import:
10. Comparison: Moment.js vs Day.js
Takeaway: Moment.js là di sản quá khứ; Day.js là tiêu chuẩn hiện tại — nhỏ hơn 97%, immutable và hoàn toàn linh hoạt.
11. Lesson Reflection — Think About It
- Kiểm tra lại dự án hiện tại của bạn:
moment.jsđang chiếm bao nhiêu % tổng dung lượng bundle JS? (Dùngwebpack-bundle-analyzerhoặcsource-map-explorer). - Có bao nhiêu nơi trong codebase của bạn đang gọi
moment().add()hoặcmoment().subtract()mà không gọi.clone()trước đó? Đó có phải là nguyên nhân của những bug ngày tháng khó hiểu? - Bạn sẽ chọn giải pháp nào cho
daterangepicker: DùngbadMutableshim tạm thời hay lên kế hoạch thay thế bằngLitepicker/Flatpickr?
12. What’s Next — Next Steps & Resources
Bài tiếp theo trong chuỗi tối ưu hóa Frontend: Tối ưu Clientlibs & Webpack Build trong AEM AMS 6.5.
- Trang chủ chính thức của Day.js
- Danh sách Plugins đầy đủ của Day.js
- Plugin-free replacement guide: You Dont Need Momentjs
- Litepicker — Thư viện Date Range Picker không cần Moment