Back

轻量级国际化:用 Intl API 替代第三方库

轻量级国际化:用 Intl API 替代第三方库

你的 JavaScript 包中包含了 Moment.js?那就是 280KB 的日期格式化代码。而原生的 JavaScript Intl API 呢?零字节。这种巨大差异代表着数千美元的带宽成本和数秒的加载时间,这些都会直接影响你的转化率。

现代 Web 应用程序不需要沉重的国际化库。JavaScript Intl API 提供了日期格式化、数字格式化、货币格式化、复数处理和字符串排序功能——所有这些都内置在浏览器中。本文将向你展示如何用原生解决方案替代 Moment.js、date-fns、numeral.js 等类似库,从而提升性能并降低复杂性。

核心要点

  • Intl API 为你的包增加零字节,而 Moment.js 等库会增加 280KB
  • 原生浏览器支持覆盖超过 99.5% 的用户——无需 polyfill
  • 用内置 API 替换日期格式化、数字格式化和复数处理
  • 在生产环境中缓存格式化器实例以获得最佳性能

为什么要用 JavaScript Intl API 替代沉重的库

包体积问题

流行的国际化库会给你的应用程序增加显著的体积:

  • Moment.js:280KB(gzip 压缩后 67KB)
  • date-fns:75KB(常用函数 gzip 压缩后 17KB)
  • numeral.js:72KB(gzip 压缩后 18KB)

当你包含本地化数据时,这些数字还会进一步增加。而 JavaScript Intl API 不需要额外的字节——它已经在浏览器中了。

2025 年的原生浏览器支持

浏览器兼容性不再是问题。Intl API 在所有现代浏览器中都有通用支持。只有 Internet Explorer 和 Opera Mini 缺乏支持——这些浏览器在全球使用率中占比不到 0.5%。你的用户已经拥有这些 API。

使用 Intl.DateTimeFormat 进行日期和时间格式化

基础日期格式化

替换 Moment.js 的日期格式化:

// 之前:Moment.js
moment().format('MMMM DD, YYYY'); // "October 3, 2025"

// 之后:原生 Intl
new Intl.DateTimeFormat('en-US', {
  year: 'numeric',
  month: 'long',
  day: 'numeric'
}).format(new Date()); // "October 3, 2025"

高级选项

原生 API 可以处理时区和复杂格式化:

new Intl.DateTimeFormat('en-GB', {
  dateStyle: 'full',
  timeStyle: 'short',
  timeZone: 'Europe/London'
}).format(new Date()); // "Friday, 3 October 2025 at 15:30"

无需库的相对时间格式化

用原生相对时间替换 moment.fromNow()

// 之前:Moment.js
moment().subtract(2, 'hours').fromNow(); // "2 hours ago"

// 之后:原生 Intl
const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
rtf.format(-2, 'hour'); // "2 hours ago"
rtf.format(1, 'day'); // "tomorrow"

该 API 自动处理复数形式和跨语言本地化。

简化的数字和货币格式化

数字格式化

用原生数字格式化替换 numeral.js:

// 之前:numeral.js
numeral(1234567.89).format('0,0.00'); // "1,234,567.89"

// 之后:原生 Intl
new Intl.NumberFormat('en-US').format(1234567.89); // "1,234,567.89"
new Intl.NumberFormat('de-DE').format(1234567.89); // "1.234.567,89"

货币格式化

原生货币格式化消除了外部依赖:

const formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
});
formatter.format(1234.5); // "$1,234.50"

// 日元(无小数位)
new Intl.NumberFormat('ja-JP', {
  style: 'currency',
  currency: 'JPY'
}).format(1234); // "¥1,234"

使用 Intl.PluralRules 的智能复数处理

用原生复数处理替换复杂的条件逻辑:

const pr = new Intl.PluralRules('en-US', { type: 'ordinal' });
const suffixes = { one: 'st', two: 'nd', few: 'rd', other: 'th' };

function ordinal(n) {
  const rule = pr.select(n);
  return `${n}${suffixes[rule]}`;
}

ordinal(1); // "1st"
ordinal(22); // "22nd"
ordinal(103); // "103rd"

使用 Intl.Collator 的本地化感知字符串排序

用原生本地化感知排序替换自定义排序:

// 数字感知排序
const collator = new Intl.Collator('en', { numeric: true });
['item2', 'item10', 'item1'].sort(collator.compare);
// ["item1", "item2", "item10"]

// 德语排序(ä 排在 a 之后)
const germanCollator = new Intl.Collator('de');
['Müller', 'Mueller', 'Maler'].sort(germanCollator.compare);
// ["Maler", "Mueller", "Müller"]

生产环境最佳实践

格式化器缓存

创建一次格式化器并重复使用:

// 缓存格式化器以提升性能
const formatters = new Map();

function getCurrencyFormatter(locale, currency) {
  const key = `${locale}-${currency}`;
  if (!formatters.has(key)) {
    formatters.set(key, new Intl.NumberFormat(locale, {
      style: 'currency',
      currency
    }));
  }
  return formatters.get(key);
}

错误处理

为无效输入实现回退机制:

function safeFormat(date, locale = 'en-US', options = {}) {
  try {
    return new Intl.DateTimeFormat(locale, options).format(date);
  } catch (error) {
    console.warn(`格式化失败,区域设置:${locale}`, error);
    return new Intl.DateTimeFormat('en-US', options).format(date);
  }
}

限制和未来考虑

Intl API 在格式化方面表现出色,但不处理日期运算。对于添加天数或计算日期差异等计算,你需要即将推出的 Temporal API 或轻量级计算库。

只有在需要以下功能时才考虑保留库:

  • 复杂的日期运算
  • 解析任意日期字符串
  • 支持 IE11 以下的旧版浏览器

结论

JavaScript Intl API 将国际化从包体积负担转变为零成本功能。通过用原生 API 替换 Moment.js、date-fns 和 numeral.js,你可以消除依赖、提升性能并简化维护。

今天就开始你的迁移:识别这些库中仅用于格式化的用途,并用 Intl 替换它们。你的用户将体验到更快的加载时间,你的应用程序也将更易于维护。最好的代码就是你不需要发布的代码。

常见问题

Intl API 处理格式化但不处理日期运算,如添加天数或计算差异。对于这些操作,请使用原生 Date 方法或等待 Temporal API。大多数应用程序只使用库进行格式化,这使得 Intl 成为完美的替代品。

仅移除 Moment.js 就能节省 280KB,在较慢的连接上减少 1-3 秒的加载时间。运行时性能也有所提升,因为原生 API 在浏览器级别进行了优化,通常比 JavaScript 库快 2-3 倍。

所有现代浏览器都支持 Intl API。只有 Internet Explorer 和 Opera Mini 缺乏支持,占用户的不到 0.5%。如果你必须支持这些浏览器,只为这些用户使用 polyfill,而不是向所有人发布沉重的库。

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay