Moment.js
曾经最流行的 JavaScript 日期处理库,现已进入维护模式(legacy),官方不再推荐用于新项目。
Moment.js 曾是最广泛使用的 JavaScript 日期时间库,以流畅链式 API 著称。由于可变对象设计、72KB 体积和无法 tree-shaking 等缺陷,2020 年官方宣布进入维护模式,推荐迁移至 Luxon、Day.js 或 date-fns。
Moment.js
曾经最流行的 JavaScript 日期处理库,现已进入维护模式(legacy),官方不再推荐用于新项目。
技术简介说明
Moment.js 曾是 JavaScript 生态中最广泛使用的日期时间处理库,以其流畅的链式 API 和丰富的功能赢得了开发者的青睐。在最辉煌的时期,Moment.js 的 npm 周下载量超过 1,700 万次,几乎是所有 JavaScript 项目的"标配"。
然而,随着前端工程化的发展,Moment.js 的设计缺陷逐渐暴露:可变对象导致的难以预料的副作用、~72KB 的臃肿体积(无法 tree-shaking)、以及对现代 Web API(如 Intl)的缺失利用。2020 年,Moment.js 团队正式宣布项目进入维护模式,不再添加新功能。
截至 2026 年,Moment.js 仍然拥有约 1,400 万周下载量——这主要来自于存量项目和遗留代码,而非新增选择。官方团队明确建议新项目使用 Luxon、Day.js、date-fns 或原生 Temporal API 替代。
基本信息
| 项目 | 详情 |
|---|---|
| 官网 | https://momentjs.com/ |
| GitHub | https://github.com/moment/moment |
| License | MIT |
| 最新版本 | v2.30.1(最终版本) |
| 主要维护者 | Moment.js 团队(Tim Wood 创建) |
| npm 周下载量 | ~1,400 万(存量项目为主) |
| GitHub Stars | 48,000+ |
| 项目状态 | ⚠️ 维护模式 / Legacy |
快速上手
安装
# npm
npm install moment
# yarn
yarn add moment
# pnpm
pnpm add moment
# CDN
<script src="https://cdn.jsdelivr.net/npm/[email protected]/moment.min.js"></script>
<!-- 中文 locale -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/locale/zh-cn.js"></script>基础配置
import moment from 'moment'
import 'moment/locale/zh-cn'
moment.locale('zh-cn') // 全局设置中文最小示例
import moment from 'moment'
// 当前时间
const now = moment()
// 格式化
console.log(now.format('YYYY-MM-DD HH:mm:ss')) // '2026-07-07 14:30:00'
// 日期计算
const tomorrow = moment().add(1, 'days')
const lastWeek = moment().subtract(1, 'weeks')
// 相对时间
console.log(moment().subtract(3, 'hours').fromNow()) // '3 小时前'
// 解析
const date = moment('2026-07-07', 'YYYY-MM-DD')核心概念与架构
可变对象设计
Moment.js 的核心设计是可变的——大多数操作会修改原始对象:
const a = moment('2026-01-01')
const b = a.add(1, 'day')
// ⚠️ a 也被修改了!a 和 b 指向同一个对象
console.log(a.format('YYYY-MM-DD')) // '2026-01-02'(已被修改)
console.log(b === a) // true这是 Moment.js 最受诟病的设计缺陷。要获取不可变行为,需要先克隆:
const a = moment('2026-01-01')
const b = a.clone().add(1, 'day')
// a 保持不变全局状态
Moment.js 使用全局状态管理 locale 和时区设置:
moment.locale('zh-cn') // 影响所有 moment 实例这在多语言应用中可能导致意外的全局副作用。
打包问题
Moment.js 会将所有 locale 文件打包在一起,导致最终产物非常臃肿。Webpack 需要使用 IgnorePlugin 排除不需要的 locale:
// webpack.config.js
const webpack = require('webpack')
module.exports = {
plugins: [
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/locale$/,
contextRegExp: /moment$/,
}),
],
}核心特性
- 流畅的链式 API:
moment().add(1, 'day').format('YYYY-MM-DD') - 丰富的格式化选项:支持数十种格式化 token
- Locale 支持:130+ 种语言
- 时区插件:
moment-timezone提供 IANA 时区支持 - 相对时间:
fromNow()、toNow()等方法 - Duration 支持:时间跨度处理
- 日历格式化:"Yesterday"、"Tomorrow" 等人性化输出
- 多语言解析:支持用不同语言解析日期字符串
- 浏览器 + Node.js:双环境支持
- 成熟的生态:10 年以上历史,大量教程和问答资源
生态图
核心扩展
| 扩展 | 功能 |
|---|---|
moment-timezone | IANA 时区支持(~180KB 数据文件) |
moment-range | 日期范围操作 |
moment-precise-range-plugin | 精确日期差计算 |
社区生态(历史积累)
- react-moment:React 组件封装
- vue-moment:Vue 过滤器
- angular-moment:Angular 集成
- moment-parseformat:自动检测日期格式
- react-dates(Airbnb):基于 Moment.js 的日期选择器
关键依赖
moment-timezone依赖 Moment.js 核心 + IANA 时区数据(~180KB)- 部分 UI 库依赖 Moment.js(如旧版 react-dates、ant-design v3 等),但这些正在迁移
适用场景
⚠️ 不推荐用于新项目
Moment.js 团队官方声明:"We now generally consider Moment to be a legacy project in maintenance mode. It is not dead, but it is indeed done."
仅推荐在以下场景继续使用:
- 遗留项目维护:已有大量 Moment.js 代码的存量项目,迁移成本高于维护成本
- 遗留 UI 组件:依赖 Moment.js 的第三方组件(如旧版 ant-design、react-dates)
- 快速脚本/原型:不考虑长期维护的一次性脚本
官方推荐替代方案
| 替代方案 | 特点 |
|---|---|
| Luxon | Moment.js 团队官方推荐,由 Moment 核心贡献者开发 |
| Day.js | 轻量(2KB),API 与 Moment.js 高度兼容 |
| date-fns | 函数式设计,tree-shakeable |
| js-Joda | Java 时间 API 的 JavaScript 移植 |
| Temporal API | JavaScript 原生日期 API(ES2026) |
开发与工程化
项目状态
Moment.js 已进入维护模式,不再有功能开发。官方仅进行:
- 关键安全补丁修复
- 时区数据更新(IANA 数据库更新)
- 不会修复 tree-shaking 问题
- 不会修复可变性问题
- 不会添加新功能
遗留项目中的 Moment.js 优化
// ✅ Webpack 排除不需要的 locale
const webpack = require('webpack')
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/locale$/,
contextRegExp: /moment$/,
})
// ✅ 只引入需要的 locale
import moment from 'moment'
import 'moment/locale/zh-cn'迁移策略
从 Moment.js 迁移到新库的一般策略:
- 评估使用范围:搜索所有
moment(调用,统计影响面 - 选择替代库:根据项目特点选择 Day.js(最小改动)、date-fns(现代化)或 Luxon(功能完整)
- 逐步替换:可以在同一项目中同时使用 Moment.js 和新库,逐步迁移
- Day.js 作为过渡:Day.js 的 API 与 Moment.js 高度兼容,可作为最小改动迁移方案
性能与安全
性能问题
- 包体积:Moment.js 核心 ~72KB(minified + gzipped),加上
moment-timezone达到 ~250KB - 无法 tree-shaking:所有功能全量打包,即使只用了
format - Locale 膨胀:默认打包所有 130+ 种 locale
可变性陷阱
// ⚠️ 经典 bug:意外的对象修改
function formatEvent(date) {
return date.startOf('day').format('YYYY-MM-DD') // 修改了传入的 date 对象!
}
const eventDate = moment('2026-07-07T15:30:00')
formatEvent(eventDate)
console.log(eventDate.format()) // 时间已被修改为 00:00:00!安全注意事项
- 浏览器 DevTools(如 Chrome)会对使用 Moment.js 的项目显示弃用警告
- 部分安全扫描工具会将 Moment.js 标记为技术债务
- 定期更新
moment-timezone以获取最新的 IANA 时区数据
技术对比
| 特性 | Moment.js | Day.js | date-fns | Luxon |
|---|---|---|---|---|
| 包大小 | ~72KB | ~2KB | ~17.5KB | ~53KB |
| 不可变 | ❌ 可变 | ✅ | ✅ | ✅ |
| Tree-shaking | ❌ | ❌(插件不支持) | ✅ 完美 | ✅ 部分 |
| TypeScript | ❌ | ✅ | ✅ | ✅ |
| 时区 | moment-timezone | 插件 | @date-fns/tz | 内置 |
| 维护状态 | ⚠️ Legacy | ✅ 活跃 | ✅ 活跃 | ✅ 活跃 |
| 学习成本 | 低 | 低 | 中 | 中 |
| 社区规模 | 大(存量) | 中 | 大 | 中 |
Moment.js 的核心问题
- 可变对象:导致难以调试的 bug,与现代 React/Vue 的不 immutable 理念冲突
- 包体积臃肿:72KB+ 的体积在现代性能标准下不可接受
- 无法 tree-shaking:即使用了 Webpack/Rollup,也无法去除未使用的代码
- 无 TypeScript 支持:官方不提供类型定义(社区 @types/moment 存在但非官方)
- 全局 locale:
moment.locale()影响全局,多语言应用有副作用风险 - 浏览器标记弃用:Chrome DevTools 等工具会标记 Moment.js 为需移除的库
最佳实践
如果你必须继续使用 Moment.js
// ✅ 总是使用 clone() 避免可变性陷阱
const result = myMoment.clone().add(1, 'day')
// ✅ 使用 strict 模式解析
moment('2026-07-07', 'YYYY-MM-DD', true)
// ✅ Webpack 中排除不需要的 locale
new webpack.IgnorePlugin({ resourceRegExp: /^\.\/locale$/, contextRegExp: /moment$/ })
// ✅ 检查日期有效性
if (moment(dateString).isValid()) {
// 处理有效日期
}迁移优先级建议
| 项目情况 | 推荐替代 |
|---|---|
| 大量 Moment.js 代码,希望最小改动 | Day.js |
| TypeScript 项目,追求现代化 | date-fns |
| 复杂时区需求 | Luxon |
| 新项目(任何情况) | 不要使用 Moment.js |
技术局限与边界
- 项目已停止开发:不会再有功能更新或重大改进
- 架构缺陷不可修复:可变性、不可 tree-shaking 等根本性问题无法在不打破兼容性的情况下修复
- 与现代框架冲突:React/Vue 的不可变数据理念与 Moment.js 的可变设计冲突
- bundle size 影响:72KB+ 的体积对移动端和 SSR 场景影响显著
- 浏览器弃用标记:DevTools 会标记 Moment.js,影响开发体验
- 安全扫描告警:部分安全/质量工具会将 Moment.js 视为技术债务
- 新开发者不熟悉:越来越多的开发者直接学习 date-fns 或 Temporal,不了解 Moment.js
学习资源
- 官方文档:https://momentjs.com/docs/
- 项目状态说明:https://momentjs.com/docs/#/-project-status/
- GitHub 仓库:https://github.com/moment/moment
- 迁移指南:https://terodox.tech/migrating-away-from-momentjs-part1/
- 为什么应该移除 Moment.js:https://www.linkedin.com/pulse/why-we-should-remove-momentjs-2025-nishant-gupta-cfukc
- PkgPulse 2026 分析:https://www.pkgpulse.com/guides/why-developers-abandoning-momentjs-2026
2026 年现状
当前版本
- v2.30.1:最终稳定版,不会再有 v2.31 或更高版本
- 仅接收安全补丁和时区数据更新
社区活跃度
- npm 周下载量约 1,400 万,但这是存量项目的惯性下载
- 新项目几乎不再选择 Moment.js
- GitHub Issues 基本处于冻结状态
- 社区讨论已转向替代方案
发展趋势
- 持续下降:Moment.js 的使用率持续下降,开发者加速向 Day.js、date-fns、Luxon 和 Temporal API 迁移
- 浏览器标记弃用:越来越多的 DevTools 和质量工具标记 Moment.js 为"应移除"
- Temporal API 终结:随着 Temporal API 成为 ES2026 标准并逐步获得浏览器原生支持,Moment.js 的替代方案将更加完善
- 教育内容更新:新的教程、课程和文档不再教授 Moment.js,转向现代替代方案
- 结论:2026 年,Moment.js 绝不应该被用于新项目。 对于存量项目,建议制定迁移计划,逐步替换为 Day.js、date-fns 或 Luxon