packages/memo-intl/README.md
# @httpx/memo-intl
LRU-based memoizer for [Intl.NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat)
and [Intl.DateFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat) constructors.
[![npm](https://img.shields.io/npm/v/@httpx/memo-intl?style=for-the-badge&label=Npm&labelColor=444&color=informational)](https://www.npmjs.com/package/@httpx/memo-intl)
[![changelog](https://img.shields.io/static/v1?label=&message=changelog&logo=github&style=for-the-badge&labelColor=444&color=informational)](https://github.com/belgattitude/httpx/blob/main/packages/memo-intl/CHANGELOG.md)
[![codecov](https://img.shields.io/codecov/c/github/belgattitude/httpx?logo=codecov&label=Unit&flag=httpx-memo-intl-unit&style=for-the-badge&labelColor=444)](https://app.codecov.io/gh/belgattitude/httpx/tree/main/packages%2Fmemo-intl)
[![bundles](https://img.shields.io/static/v1?label=&message=cjs|esm@treeshake&logo=webpack&style=for-the-badge&labelColor=444&color=informational)](https://github.com/belgattitude/httpx/blob/main/packages/memo-intl/.size-limit.cjs)
[![node](https://img.shields.io/static/v1?label=Node&message=18%2b&logo=node.js&style=for-the-badge&labelColor=444&color=informational)](#compatibility)
[![browserslist](https://img.shields.io/static/v1?label=Browser&message=%3E96%25&logo=googlechrome&style=for-the-badge&labelColor=444&color=informational)](#compatibility)
[![size](https://img.shields.io/bundlephobia/minzip/@httpx/memo-intl@latest?label=Max&style=for-the-badge&labelColor=444&color=informational)](https://bundlephobia.com/package/@httpx/memo-intl@latest)
[![downloads](https://img.shields.io/npm/dm/@httpx/memo-intl?style=for-the-badge&labelColor=444)](https://www.npmjs.com/package/@httpx/memo-intl)
[![license](https://img.shields.io/npm/l/@httpx/memo-intl?style=for-the-badge&labelColor=444)](https://github.com/belgattitude/httpx/blob/main/LICENSE)
## Install
```bash
$ npm install @httpx/memo-intl
$ yarn add @httpx/memo-intl
$ pnpm add @httpx/memo-intl
```
## Features
- π Don't re-create the same Intl instance for the same options (memoized).
- π Keep the [Intl](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) api untouched. Just replace `new Intl.NumberFormat` by `MIntl.NumberFormat`...
- π Up to 20x faster than non-memoized Intl constructors.
- π Decrease memory usage, unwanted memory leaks and garbage collection pressure.
- π Max out 50 cache instances by default with [quick-lru](https://github.com/sindresorhus/quick-lru).
- π Lightweight. [Node, browser and edge support](#compatibility).
## Documentation
π [Official website](https://belgattitude.github.io/httpx/memo-intl) or [Github Readme](https://github.com/belgattitude/httpx/tree/main/packages/memo-intl#readme)
## Usage
### MIntl.NumberFormat
```typescript
import { MIntl } from '@httpx/memo-intl';
// Notice: `new Intl.NumberFormat` vs `MIntl.NumberFormat`
const formattedPrice = MIntl.NumberFormat('fr-FR', {
style: 'currency',
currency: 'EUR',
notation: 'compact',
minimumFractionDigits: 2,
}).format(row.price);
```
### MIntl.DateTimeFormat
```typescript
import { MIntl } from '@httpx/memo-intl';
// Notice: `new Intl.DateTimeFormat` vs `MIntl.DateTimeFormat
const formatter = MIntl.DateTimeFormat('fr-FR', {
dateStyle: 'full',
timeStyle: 'full',
timeZone: 'UTC'
});
const date = Date.parse('2024-05-29T07:42:43.230Z');
expect(formatter.format(date)).toBe(
'mercredi 29 mai 2024 Γ 07:42:43 temps universel coordonnΓ©'
);
expectTypeOf(formatter).toEqualTypeOf<Intl.DateTimeFormat>();
```
## Benchmarks
Performance is monitored with [codspeed.io](https://codspeed.io/belgattitude/httpx).
[![CodSpeed Badge](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/belgattitude/httpx)
`IntlNumberFormat(locale, options) x 10_000`, see [bench](https://github.com/belgattitude/httpx/blob/main/packages/memo-intl/bench/m-intl.bench.ts) for details.
```
RUN v1.6.0 /home/sebastien/github/httpx/packages/memo-intl
β bench/m-intl.bench.ts (2) 3626ms
β MIntl benchmarks (2) 3624ms
name hz min max mean p75 p99 p995 p999 rme samples
Β· With memoization `MIntl.NumberFormat()` 108.24 8.6995 10.5676 9.2388 9.8779 10.5676 10.5676 10.5676 Β±5.22% 10 fastest
Β· Without memoization `new Intl.NumberFormat()` 5.0021 192.58 210.78 199.92 201.81 210.78 210.78 210.78 Β±1.81% 10
BENCH Summary
With memoization `MIntl.NumberFormatter()` - bench/m-intl.bench.ts > MIntl benchmarks
21.64x faster than Without memoization `new Intl.NumberFormatter()`
```
## Bundle size
Bundle size is tracked by a [size-limit configuration](https://github.com/belgattitude/httpx/blob/main/packages/memo-intl/.size-limit.cjs)
| Scenario | Size with deps (compressed) |
|------------------------------------------------|----------------------------:|
| `import { MIntl } from '@httpx/memo-intl' | ~ 1.2kB |
> Note that per-se the library weigths less than 300 bytes, the quick-lru dependency makes the difference.
> For CJS usage (not recommended) track the size on [bundlephobia](https://bundlephobia.com/package/@httpx/memo-intl@latest).
## Compatibility
| Level | CI | Description |
|--------------|----|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Node | β
| CI for 18.x, 20.x & 22.x. |
| Browser | β
| Tested with latest chrome (vitest/playwright) |
| Browserslist | β
| [> 96%](https://browserslist.dev/?q=ZGVmYXVsdHMsIGNocm9tZSA%2BPSA5NixmaXJlZm94ID49IDkwLGVkZ2UgPj0gMTksc2FmYXJpID49IDEyLGlvcyA%2BPSAxMixvcGVyYSA%2BPSA3Nw%3D%3D) on 12/2023. Mins to [Chrome 96+, Firefox 90+, Edge 19+, iOS 12+, Safari 12+, Opera 77+](https://github.com/belgattitude/httpx/blob/main/packages/memo-intl/.browserslistrc) |
| Edge | β
| Ensured on CI with [@vercel/edge-runtime](https://github.com/vercel/edge-runtime). |
| Cloudflare | β
| Ensured with @cloudflare/vitest-pool-workers (see [wrangler.toml](https://github.com/belgattitude/httpx/blob/main/devtools/vitest/wrangler.toml) |
| Typescript | β
| TS 5.0 + / [are-the-type-wrong](https://github.com/arethetypeswrong/arethetypeswrong.github.io) checks on CI. |
| ES2022 | β
| Dist files checked with [es-check](https://github.com/yowainwright/es-check) |
| Performance| β
| Monitored with with [codspeed.io](https://codspeed.io/belgattitude/httpx) |
> For _older_ browsers: most frontend frameworks can transpile the library (ie: [nextjs](https://nextjs.org/docs/app/api-reference/next-config-js/transpilePackages)...)
## Contributors
Contributions are warmly appreciated. Have a look to the [CONTRIBUTING](https://github.com/belgattitude/httpx/blob/main/CONTRIBUTING.md) document.
## Sponsors
If my OSS work brightens your day, let's take it to new heights together!
[Sponsor](<[sponsorship](https://github.com/sponsors/belgattitude)>), [coffee](<(https://ko-fi.com/belgattitude)>),
or star β any gesture of support fuels my passion to improve. Thanks for being awesome! πβ€οΈ
### Special thanks to
<table>
<tr>
<td>
<a href="https://www.jetbrains.com/?ref=belgattitude" target="_blank">
<img width="65" src="https://asset.brandfetch.io/idarKiKkI-/id53SttZhi.jpeg" alt="Jetbrains logo" />
</a>
</td>
<td>
<a href="https://www.embie.be/?ref=belgattitude" target="_blank">
<img width="65" src="https://avatars.githubusercontent.com/u/98402122?s=200&v=4" alt="Jetbrains logo" />
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://www.jetbrains.com/?ref=belgattitude" target="_blank">JetBrains</a>
</td>
<td align="center">
<a href="https://www.embie.be/?ref=belgattitude" target="_blank">Embie.be</a>
</td>
</tr>
</table>
## License
MIT Β© [belgattitude](https://github.com/belgattitude) and contributors.