nanoid Documentation

A tiny (118 bytes), secure, URL-friendly, unique string ID generator for JavaScript

26,924 stars JavaScript JavaScript 1 file · ~17,517 tokens
RAW Doc

File: README.md

Nano ID

English | 日本語 | Русский | 简体中文 | Bahasa Indonesia | 한국어 | العربية

A tiny, secure, URL-friendly, unique string ID generator for JavaScript.

“An amazing level of senseless perfectionism,
which is simply impossible not to respect.”

  • Small. 118 bytes (minified and brotlied). No dependencies.
    Size Limit controls the size.
  • Fast. 50% faster than native crypto.randomUUID().
  • Safe. It uses hardware random generator. Can be used in clusters.
  • Short IDs. It uses a larger alphabet than UUID (A-Za-z0-9_-).
    So ID size was reduced from 36 to 21 symbols.
  • Portable. Nano ID was ported
    to over 20 programming languages.
js
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

  Nano ID is built by Evil Martians, an American design and engineering consultancy for developer tools, AI, and cybersecurity startups.


Table of Contents

Comparison with UUID

Nano ID is quite comparable to UUID v4 (random-based).
It has a similar number of random bits in the ID
(126 in Nano ID and 122 in UUID), so it has a similar collision probability:

For there to be a one in a billion chance of duplication,
103 trillion version 4 IDs must be generated.

There are two main differences between Nano ID and UUID v4:

  1. Nano ID uses a bigger alphabet, so a similar number of random bits
    are packed in just 21 symbols instead of 36.
  2. Nano ID is faster than crypto.randomUUID and uuid/v4.

Benchmark

rust
$ node ./test/benchmark.js
nope-id                 20,386,830 ops/sec
nanoid                  20,434,827 ops/sec
customAlphabet          20,544,476 ops/sec
crypto.randomUUID       12,865,759 ops/sec
uuid v4                  7,930,104 ops/sec
@napi-rs/uuid            5,573,171 ops/sec
uid/secure               6,308,267 ops/sec
@lukeed/uuid             5,278,597 ops/sec
nanoid for browser         311,497 ops/sec
secure-random-string       301,667 ops/sec
uid-safe.sync              297,815 ops/sec

Non-secure:
uid                     20,286,757 ops/sec
nanoid/non-secure        2,397,594 ops/sec
rndm                     2,445,462 ops/sec

Security

See a good article about random generators theory:
Secure random values (in Node.js)

  • Unpredictability. Instead of using the unsafe Math.random(), Nano ID
    uses the crypto module in Node.js and the Web Crypto API in browsers.
    These modules use unpredictable hardware random generator.

  • Uniformity. random % alphabet is a popular mistake to make when coding
    an ID generator. The distribution will not be even; there will be a lower
    chance for some symbols to appear compared to others. So, it will reduce
    the number of tries when brute-forcing. Nano ID uses a better algorithm
    and is tested for uniformity.

  • Well-documented: all Nano ID hacks are documented. See comments
    in the source.

  • Vulnerabilities: to report a security vulnerability, please use
    the Tidelift security contact.
    Tidelift will coordinate the fix and disclosure.

Install

bash
npm install nanoid

JSR

JSR is a replacement for npm with open governance
and active development (in contrast to npm).

bash
npx jsr add @sitnik/nanoid

You can use it in Node.js, Deno, Bun, etc.

js
// Replace `nanoid` to `@sitnik/nanoid` in all imports
import { nanoid } from '@sitnik/nanoid'

For Deno install it by deno add jsr:@sitnik/nanoid or import
from jsr:@sitnik/nanoid.

CDN

For quick hacks, you can load Nano ID from CDN. Though, it is not recommended
to be used in production because of the lower loading performance.

js
import { nanoid } from 'https://cdn.jsdelivr.net/npm/nanoid/nanoid.js'

API

By default, Nano ID uses URL-friendly symbols (A-Za-z0-9_-) and returns an ID
with 21 characters (to have a collision probability similar to UUID v4).

js
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

If you want to reduce the ID size (and increase collisions probability),
you can pass the size as an argument.

js
nanoid(10) //=> "IRFa-VaY2b"

Don’t forget to check the safety of your ID size
in our ID collision probability calculator.

You can also use a custom alphabet
or a random generator.

Custom Alphabet or Size

customAlphabet returns a function that allows you to create nanoid
with your own alphabet and ID size.

js
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
model.id = nanoid() //=> "4f90d13a42"
js
import { customAlphabet } from 'nanoid/non-secure'
const nanoid = customAlphabet('1234567890abcdef', 10)
user.id = nanoid()

Check the safety of your custom alphabet and ID size in our
ID collision probability calculator. For more alphabets, check out the options
in nanoid-dictionary.

Alphabet must contain 256 symbols or less.
Otherwise, the security of the internal generator algorithm is not guaranteed.

In addition to setting a default size, you can change the ID size when calling
the function:

js
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
model.id = nanoid(5) //=> "f01a2"

Custom Random Bytes Generator

customRandom allows you to create a nanoid and replace alphabet
and the default random bytes generator.

In this example, a seed-based generator is used:

js
import { customRandom } from 'nanoid'

const rng = seedrandom(seed)
const nanoid = customRandom('abcdef', 10, size => {
  return new Uint8Array(size).map(() => 256 * rng())
})

nanoid() //=> "fbaefaadeb"

random callback must accept the array size and return an array
with random numbers.

If you want to use the same URL-friendly symbols with customRandom,
you can get the default alphabet using the urlAlphabet.

js
import { customRandom, urlAlphabet } from 'nanoid'
const nanoid = customRandom(urlAlphabet, 10, random)

Note, that between Nano ID versions we may change random generator
call sequence. If you are using seed-based generators, we do not guarantee
the same result.

Non-Secure

Nano ID uses hardware random bytes generation for security and low collision
probability. If you are not so concerned with security, you can use it
for environments without hardware random generators.

js
import { nanoid } from 'nanoid/non-secure'
const id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ"

Note, that non-secure version is slower than secure.
Use it only if you have to.

Usage

React

There’s no correct way to use Nano ID for React key prop
since it should be consistent among renders.

jsx
function Todos({ todos }) {
  return (
    
      {todos.map(todo => (
        <li key={nanoid()}>
          {' '}
          /* DON’T DO IT */
          {todo.text}
        </li>
      ))}
    
  )
}

You should rather try to reach for stable ID inside your list item.

jsx
const todoItems = todos.map(todo => <li key={todo.id}>{todo.text}</li>)

In case you don’t have stable IDs you'd rather use index as key
instead of nanoid():

jsx
const todoItems = todos.map((text, index) => (
  <li key={index}>
    {' '}
    /* Still not recommended but preferred over nanoid(). Only do this if items
    have no stable IDs. */
    {text}
  </li>
))

In case you just need random IDs to link elements like labels
and input fields together, useId is recommended.
That hook was added in React 18.

React Native

React Native does not have built-in random generator. The following polyfill
works for plain React Native and Expo starting with 39.x.

  1. Check react-native-get-random-values docs and install it.
  2. Import it before Nano ID.
js
import 'react-native-get-random-values'
import { nanoid } from 'nanoid'

PouchDB and CouchDB

In PouchDB and CouchDB, IDs can’t start with an underscore _.
A prefix is required to prevent this issue, as Nano ID might use a _
at the start of the ID by default.

Override the default ID with the following option:

js
db.put({
  _id: 'id' + nanoid(),
  …
})

CLI

You can get unique ID in terminal by calling npx nanoid. You need only
Node.js in the system. You do not need Nano ID to be installed anywhere.

sh
$ npx nanoid
npx: installed 1 in 0.63s
LZfXLFzPPR4NNrgjlWDxn

Size of generated ID can be specified with --size (or -s) option:

sh
$ npx nanoid --size 10
L3til0JS4z

Custom alphabet can be specified with --alphabet (or -a) option
(note that in this case --size is required):

sh
$ npx nanoid --alphabet abc --size 15
bccbcabaabaccab

TypeScript

Nano ID allows casting generated strings into opaque strings in TypeScript.
For example:

ts
declare const userIdBrand: unique symbol
type UserId = string & { [userIdBrand]: true }

// Use explicit type parameter:
mockUser(nanoid())

interface User {
  id: UserId
  name: string
}

const user: User = {
  // Automatically casts to UserId:
  id: nanoid(),
  name: 'Alice'
}

Other Programming Languages

Nano ID was ported to many languages. You can use these ports to have
the same ID generator on the client and server side.

For other environments, CLI is available to generate IDs from a command line.

Tools


File: README.id-ID.md

Nano ID

English | 日本語 | Русский | 简体中文 | Bahasa Indonesia | 한국어 | العربية

Sebuah generator ID yang unik dalam bentuk string yang ringan, aman, serta URL-friendly untuk JavaScript.

"Sebuah tingkat kesempurnaan yang luar biasa,
yang mana tidak mungkin untuk tidak dihormati."

  • Ringan. Hanya 118 bytes (diperkecil dan brotlied). Tidak ada ketergantungan (dependencies) apapun. Size Limit mengatur ukuran dari generator ini.
  • Cepat. 50% lebih cepat ketimbang crypto.randomUUID() bawaan.
  • Aman. Nano ID menggunakan RNG yang terdapat pada perangkat keras. Dapat digunakan dalam lingkungan seperti klaster.
  • ID yang pendek. Nano ID menggunakan alfabet yang lebih banyak ketimbang UUID (A-Za-z0-9_-), karenanya ukuran ID menjadi berkurang dari 36 menjadi 21 simbol.
  • Portabel. Nano ID telah dimigrasi untuk 20 bahasa pemrograman lainnya.
js
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

Mendukung penjelajah (browser) modern, IE dengan Babel, Node.js, dan React Native.


  Nano ID dibuat oleh Evil Martians, konsultan desain dan rekayasa asal Amerika untuk startup developer tools, AI, dan keamanan siber.


Table of Contents

Perbandingan dengan UUID

Nano ID dapat dibandingkan dengan UUID v4 (yang berbasis acak / randomly generated). Nano ID dan UUID v4 memiliki jumlah bita yang mirip pada ID yang dihasilkan (126 bita pada NanoID dan 122 bita pada UUID), karenanya ia memiliki probabilitas collision (konflik / tabrakan) yang hampir serupa:

Agar timbul kemungkinan collison / duplikasi ID satu dalam satu miliar, perlu dihasilkan 103 triliun UUID v4.

Ada dua buah perbedaan antara Nano ID dan UUID v4:

  1. Nano ID menggunakan alfabet yang lebih lebar, karenanya jumlah bita acak dapat 'dikemas' dalam 21 simbol, bukan 36 simbol.
  2. Nano ID lebih cepat ketimbang crypto.randomUUID dan uuid/v4.

Benchmark

rust
$ node ./test/benchmark.js
nope-id                 20,386,830 ops/sec
nanoid                  20,434,827 ops/sec
customAlphabet          20,544,476 ops/sec
crypto.randomUUID       12,865,759 ops/sec
uuid v4                  7,930,104 ops/sec
@napi-rs/uuid            5,573,171 ops/sec
uid/secure               6,308,267 ops/sec
@lukeed/uuid             5,278,597 ops/sec
nanoid for browser         311,497 ops/sec
secure-random-string       301,667 ops/sec
uid-safe.sync              297,815 ops/sec

Non-secure:
uid                     20,286,757 ops/sec
nanoid/non-secure        2,397,594 ops/sec
rndm                     2,445,462 ops/sec

Keamanan

Lihat artikel yang informatif tentang teori angka acak: Nilai acak yang aman dalam Node.js (English).

  • Ketidakpastian. Sebagai ganti untuk penggunaan Math.random(), Nano ID menggunakan modul crypto yang ada di dalam Nodejs dan/atau Web Crypto API dalam penjelajah (browser). Modul-modul ini menggunakan generator acak berbasis perangkat keras yang tidak bisa diprediksi untuk mendapatkan nilai-nilai yang tidak pasti yang aman secara kriptografis.

  • Keseragaman. Pembagian dengan rumus random % alphabet adalah kesalahan yang seringkali dilakukan ketika merancang sebuah generator ID. Distribusi dari nilai-nilai tersebut tidak akan seimbang; dalam artian ada kesempatan untuk beberapa simbol untuk muncul dibandingkan dengan simbol yang lain. Ini memiliki dampak yang kurang baik, yakni mengurangi jumlah percobaan ketika seseorang mencoba untuk melakukan brute-force attacks. Nano ID menggunakan algoritma yang lebih baik dan sudah diuji untuk keseragamannya.

  • Terdokumentasi secara baik. Seluruh algoritma Nano ID sudah terdokumentasi. Lihat komentar di kode sumber.

  • Kerentanan. Untuk melaporkan sebuah security vulnerability atau kerentanan, mohon menggunakan Tidelift Security Contact. Tidelift akan mengkoordinasikan pembetulan dan penyingkapan dari kerentanan tersebut.

Instalasi

bash
npm install nanoid

Apabila ingin 'coba-coba' terlebih dahulu, dapat digunakan Nano ID melalui CDN. Hal ini tidak direkomendasikan untuk digunakan pada lingkungan produksi karena performa pemuatan (loading) yang berkurang.

js
import { nanoid } from 'https://cdn.jsdelivr.net/npm/nanoid/nanoid.js'

API

Bawaannya, Nano ID menggunakan simbol yang URL-friendly (A-Za-z0-9_-) dan mengembalikan ID dengan 21 karakter (untuk memiliki probabilitas collision / tabrakan yang mirip dengan UUID v4).

js
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

Apabila ingin mengurangi ukuran ID (dan meningkatkan probabilitas collision), dapat dimasukkan size sebagai argumen dari fungsi nanoid().

js
nanoid(10) //=> "IRFa-VaY2b"

Jangan lupa memeriksa tingkat keamanan dari ukuran ID dalam situs ID collision probability calculator.

Dapat digunakan pula custom alphabet atau random generator yang lain.

Alfabet dan Ukuran (Custom)

customAlphabet digunakan untuk membuat Nano ID dengan alfabet dan ukuran ID yang sesuai dengan kebutuhan (dapat dikustomisasi).

js
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
model.id = nanoid() //=> "4f90d13a42"

Ketika menggunakan fungsi ini, jangan lupa untuk memeriksa keamanan alfabet dan ukuran ID dalam ID collision probability calculator. Untuk lebih banyak alfabet, dapat menggunakan nanoid-dictionary.

Alfabet harus terbentuk dari 256 simbol atau lebih kecil. Selain itu, keamanan algoritma generasi yang berada di dalam library ini tidak dijamin aman.

API non-secure yang dapat dikustomisasi dengan customAlphabet pun tersedia disini:

js
import { customAlphabet } from 'nanoid/non-secure'
const nanoid = customAlphabet('1234567890abcdef', 10)
user.id = nanoid()

Generasi Random Bytes (Custom)

customRandom digunakan untuk membuat Nano ID yang mengganti alfabet dan algoritma random bytes generator yang telah diimplementasikan pada versi bawaan (dalam artian menggunakan algoritma sendiri untuk mendapatkan random bytes).

Pada contoh berikut, digunakan seed-based generator:

js
import { customRandom } from 'nanoid'

const rng = seedrandom(seed)
const nanoid = customRandom('abcdef', 10, size => {
  return new Uint8Array(size).map(() => 256 * rng())
})

nanoid() //=> "fbaefaadeb"

Fungsi callback pada random harus menerima ukuran array dan mengembalikan sebuah array dengan angka acak.

Apabila ingin menggunakan alfabet bawaan NanoID pada fungsi customRandom, dapat menggunakan konstanta urlAlphabet seperti berikut:

js
const { customRandom, urlAlphabet } = require('nanoid')
const nanoid = customRandom(urlAlphabet, 10, random)

API asinkronus dan non-secure tidak tersedia untuk fungsi customRandom.

Non-Secure

Nano ID menggunakan random bytes generator yang berasal dari perangkat keras untuk keamanan dan probabilitas collision yang rendah. Apabila tidak terlalu memikirkan soal keamanan, dapat pula menggunakannya pada lingkungan tanpa hardware random generator.

js
import { nanoid } from 'nanoid/non-secure'
const id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ"

Perlu dicatat bahwa versi non-secure lebih lambat daripada versi secure. Gunakan hanya jika benar-benar diperlukan.

Penggunaan

React

Dalam React, tidak ada cara yang benar bila ingin menggunakan Nano ID untuk prop key, karena key tersebut harus konsisten dalam setiap proses render yang terjadi.

jsx
function Todos({ todos }) {
  return (
    
      {todos.map(todo => (
        /* JANGAN DILAKUKAN! */
        <li key={nanoid()}>{todo.text}</li>
      ))}
    
  )
}

Karena hal tersebut, disarankan untuk menggunakan ID yang stabil pada setiap objek yang di-render oleh React.

jsx
const todoItems = todos.map(todo => <li key={todo.id}>{todo.text}</li>)

Apabila tidak memiliki ID yang stabil pada setiap item yang di-render pada React, lebih baik menggunakan indeks sebuah array sebagai key ketimbang menggunakan fungsi nanoid(), seperti berikut:

jsx
const todoItems = todos.map((text, index) => (
  /* Tetap tidak direkomendasikan, tetapi lebih disarankan dari 'nanoid()'. Lakukan ini
    apabila setiap objek / item dalam list tidak ada ID yang stabil. */
  <li key={index}>{text}</li>
))

React Native

React Native tidak memiliki built-in random generator. Digunakan polyfill seperti berikut yang berjalan untuk React Native dan Expo yang bermula dari versi 39.x.

  1. Periksa dokumentasi react-native-get-random-values dan install di aplikasi.
  2. Import library tersebut sebelum Nano ID.
js
import 'react-native-get-random-values'
import { nanoid } from 'nanoid'

PouchDB dan CouchDB

Dalam PouchDB dan CouchDB, ID tidak bisa dimulai dengan underscore _. Sebuah prefix dibutuhkan untuk mencegah hal ini terjadi, karena Nano ID mungkin menggunakan _ sebagai karakter pertama dari ID yang dihasilkan.

ID bawaan dapat diubah dengan opsi berikut:

js
db.put({
  _id: 'id' + nanoid(),
  …
})

CLI

Nano ID dapat didapatkan dengan cara menggunakan npx nanoid pada Terminal. Hanya diperlukan Node.js untuk ini, dan tidak perlu mengunduh dan menginstall Nano ID dalam sistem.

sh
$ npx nanoid
npx: installed 1 in 0.63s
LZfXLFzPPR4NNrgjlWDxn

Bila ingin mengganti alfabet atau ukuran ID, dapat menggunakan nanoid-cli.

TypeScript

Nano ID memungkinkan untuk mengubah string yang dihasilkan menjadi string opak
dalam TypeScript. Sebagai contoh:

ts
declare const userIdBrand: unique symbol
type UserId = string & { [userIdBrand]: true }

// Gunakan parameter tipe secara eksplisit:
mockUser(nanoid())

interface User {
  id: UserId
  name: string
}

const user: User = {
  // Secara otomatis diubah menjadi UserId:
  id: nanoid(),
  name: 'Alice'
}

Bahasa Pemrograman Lainnya

Nano ID telah bermigrasi ke berbagai macam bahasa. Seluruh versi dapat digunakan untuk mendapatkan ID generator yang sama pada sisi klien dan sisi penyedia layanan (client-side dan server-side).

Untuk environment lainnya, CLI tersedia untuk melakukan generasi ID dari command line / Terminal.

Alat

  • ID Size Calculator menunjukkan probabilitas collision ketika melakukan konfigurasi alfabet dan ukuran.
  • nanoid-dictionary untuk menggunakan alfabet popular dalam fungsi customAlphabet
  • nanoid-good untuk meyakinkan bahwa ID yang di-generasi tidak memiliki kata-kata yang kurang baik (kasar, tidak sopan, dsb.).

File: README.ja.md

Nano ID

English | 日本語 | Русский | 简体中文 | Bahasa Indonesia | 한국어 | العربية

JavaScriptのための小さく、安全で、URL友好的なユニークな文字列ID生成器。

「意味不明なレベルの完璧主義、
これは尊敬せざるを得ない。」

  • 小さい。 118バイト(圧縮・brotli圧縮後)。依存関係なし。
    Size Limitがサイズを管理。
  • 高速。 ネイティブのcrypto.randomUUID()より50%高速。
  • 安全。 ハードウェア乱数生成器を使用。クラスタでも利用可能。
  • 短いID。 UUIDより大きなアルファベット(A-Za-z0-9_-)を使用。
    そのためID長は36から21文字に短縮されています。
  • 移植性。 Nano IDは20以上のプログラミング言語に移植されています。
js
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

  Nano ID は Evil Martians が開発しています。私たちは開発者ツール、AI、サイバーセキュリティのスタートアップを支援するアメリカのデザイン・エンジニアリングコンサルティング会社です。


目次

UUIDとの比較

Nano IDはUUID v4(ランダムベース)と十分に比較可能です。
ID内のランダムビット数は同様です(Nano IDで126ビット、UUIDで122ビット)、
そのため衝突確率も同様です:

10億分の1の確率で重複が発生するには、
103兆個のバージョン4 IDを生成する必要があります。

Nano IDとUUID v4の主な違いは2つあります:

  1. Nano IDはより大きなアルファベットを使用するため、同様のランダムビット数が
    36文字ではなく21文字に詰め込まれています。
  2. Nano IDはcrypto.randomUUIDやuuid/v4よりも高速です。

ベンチマーク

rust
$ node ./test/benchmark.js
nope-id                 20,386,830 ops/sec
nanoid                  20,434,827 ops/sec
customAlphabet          20,544,476 ops/sec
crypto.randomUUID       12,865,759 ops/sec
uuid v4                  7,930,104 ops/sec
@napi-rs/uuid            5,573,171 ops/sec
uid/secure               6,308,267 ops/sec
@lukeed/uuid             5,278,597 ops/sec
nanoid for browser         311,497 ops/sec
secure-random-string       301,667 ops/sec
uid-safe.sync              297,815 ops/sec

Non-secure:
uid                     20,286,757 ops/sec
nanoid/non-secure        2,397,594 ops/sec
rndm                     2,445,462 ops/sec

セキュリティ

乱数生成器の理論に関する良い記事を参照してください:
Secure random values (in Node.js)

  • 予測不可能性。 安全でないMath.random()を使う代わりに、Nano IDは
    Node.jsではcryptoモジュールを、ブラウザではWeb Crypto APIを使用します。
    これらのモジュールは予測不可能なハードウェア乱数生成器を使用します。

  • 均一性。 random % alphabetはID生成器をコーディングする際によくある間違いです。
    分布は均一ではなく、一部の記号が他のものより出現確率が低くなります。
    そのため、総当たり攻撃の際に試行回数が減少します。Nano IDはより良いアルゴリズムを
    使用し、均一性についてテストされています。

  • 十分に文書化されている: Nano IDのすべてのハックは文書化されています。
    ソースのコメントを参照してください。

  • 脆弱性: セキュリティの脆弱性を報告するには、
    Tideliftセキュリティ連絡先を使用してください。
    Tideliftが修正と開示を調整します。

インストール

bash
npm install nanoid

JSR

JSRはオープンなガバナンスと積極的な開発(npmとは対照的に)を持つnpmの代替です。

bash
npx jsr add @sitnik/nanoid

Node.js、Deno、Bunなどで使用できます。

js
// すべてのインポートで`nanoid`を`@sitnik/nanoid`に置き換える
import { nanoid } from '@sitnik/nanoid'

Denoでは、deno add jsr:@sitnik/nanoidでインストールするか、
jsr:@sitnik/nanoidからインポートします。

CDN

クイックハックの場合、CDNからNano IDを読み込むことができます。ただし、読み込みパフォーマンスが低いため、本番環境での使用はお勧めしません。

js
import { nanoid } from 'https://cdn.jsdelivr.net/npm/nanoid/nanoid.js'

API

デフォルトでは、Nano IDはURL友好的な記号(A-Za-z0-9_-)を使用し、
21文字のID(UUID v4と同様の衝突確率を持つ)を返します。

js
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

IDのサイズを小さくしたい場合(衝突確率を高める)、
サイズを引数として渡すことができます。

js
nanoid(10) //=> "IRFa-VaY2b"

IDサイズの安全性をID衝突確率計算機で確認することを忘れないでください。

カスタムアルファベットや
ランダム生成器も使用できます。

カスタムアルファベットまたはサイズ

customAlphabetは、独自のアルファベットとIDサイズでnanoidを作成できる関数を返します。

js
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
model.id = nanoid() //=> "4f90d13a42"
js
import { customAlphabet } from 'nanoid/non-secure'
const nanoid = customAlphabet('1234567890abcdef', 10)
user.id = nanoid()

カスタムアルファベットとIDサイズの安全性をID衝突確率計算機で確認してください。
より多くのアルファベットについては、nanoid-dictionaryのオプションを確認してください。

アルファベットは256記号以下でなければなりません。
そうでない場合、内部生成アルゴリズムのセキュリティは保証されません。

デフォルトサイズを設定するだけでなく、関数を呼び出す際にIDサイズを変更することもできます:

js
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
model.id = nanoid(5) //=> "f01a2"

カスタムランダムバイト生成器

customRandomを使用すると、nanoidを作成し、アルファベットとデフォルトのランダムバイト生成器を置き換えることができます。

この例では、シードベースの生成器が使用されています:

js
import { customRandom } from 'nanoid'

const rng = seedrandom(seed)
const nanoid = customRandom('abcdef', 10, size => {
  return new Uint8Array(size).map(() => 256 * rng())
})

nanoid() //=> "fbaefaadeb"

randomコールバックは配列サイズを受け取り、ランダムな数値の配列を返す必要があります。

customRandomで同じURL友好的な記号を使用したい場合は、urlAlphabetを使用してデフォルトのアルファベットを取得できます。

js
const { customRandom, urlAlphabet } = require('nanoid')
const nanoid = customRandom(urlAlphabet, 10, random)

なお、Nano IDのバージョン間でランダム生成器の呼び出しシーケンスが変更される場合があります。シードベースの生成器を使用している場合、同じ結果を保証するものではありません。

非セキュア

Nano IDはセキュリティと低衝突確率のためにハードウェアランダムバイト生成を使用します。セキュリティにそれほど関心がない場合は、ハードウェア乱数生成器がない環境でも使用できます。

js
import { nanoid } from 'nanoid/non-secure'
const id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ"

なお、非セキュア版はセキュア版よりも遅いことに注意してください。どうしても必要な場合のみ使用してください。

使用方法

React

Reactのkey propにNano IDを使用する正しい方法はありません。なぜなら、keyはレンダー間で一貫性がある必要があるからです。

jsx
function Todos({ todos }) {
  return (
    
      {todos.map(todo => (
        <li key={nanoid()}>
          {' '}
          /* これはやめましょう */
          {todo.text}
        </li>
      ))}
    
  )
}

代わりに、リストアイテム内で安定したIDを使用するようにしましょう。

jsx
const todoItems = todos.map(todo => <li key={todo.id}>{todo.text}</li>)

安定したIDがない場合は、nanoid()の代わりにインデックスをkeyとして使用することをお勧めします:

jsx
const todoItems = todos.map((text, index) => (
  <li key={index}>
    {' '}
    /* まだ推奨されませんが、nanoid()よりは優先されます。
    アイテムに安定したIDがない場合のみ行ってください。 */
    {text}
  </li>
))

ラベルと入力フィールドのように要素を関連付けるためだけにランダムなIDが必要な場合は、useIdが推奨されます。
このフックはReact 18で追加されました。

React Native

React Nativeには組み込みのランダム生成器がありません。次のポリフィルは
プレーンなReact NativeとExpo(39.x以降)で動作します。

  1. react-native-get-random-valuesのドキュメントを確認し、インストールします。
  2. Nano IDの前にインポートします。
js
import 'react-native-get-random-values'
import { nanoid } from 'nanoid'

PouchDBとCouchDB

PouchDBとCouchDBでは、IDはアンダースコア_で始めることができません。
Nano IDはデフォルトでIDの先頭に_を使用する可能性があるため、
この問題を防ぐためにプレフィックスが必要です。

次のオプションでデフォルトのIDを上書きします:

js
db.put({
  _id: 'id' + nanoid(),
  …
})

CLI

ターミナルでnpx nanoidを呼び出すことで、一意のIDを取得できます。
システムにNode.jsがあれば十分で、Nano IDをどこかにインストールする必要はありません。

sh
$ npx nanoid
npx: installed 1 in 0.63s
LZfXLFzPPR4NNrgjlWDxn

生成されるIDのサイズは--size(または-s)オプションで指定できます:

sh
$ npx nanoid --size 10
L3til0JS4z

カスタムアルファベットは--alphabet(または-a)オプションで指定できます
(この場合、--sizeが必須であることに注意してください):

sh
$ npx nanoid --alphabet abc --size 15
bccbcabaabaccab

TypeScript

Nano IDでは、生成された文字列をTypeScriptで不透明な文字列(opaque strings)にキャストできます。
例えば:

ts
declare const userIdBrand: unique symbol
type UserId = string & { [userIdBrand]: true }

// 明示的な型パラメータを使用:
mockUser(nanoid())

interface User {
  id: UserId
  name: string
}

const user: User = {
  // 自動的にUserIdにキャストされます:
  id: nanoid(),
  name: 'Alice'
}

その他のプログラミング言語

Nano IDは多くの言語に移植されています。これらのポートを使用して、
クライアント側とサーバー側で同じID生成器を持つことができます。

その他の環境では、コマンドラインからIDを生成するためのCLIが利用可能です。

ツール

  • IDサイズ計算機は、IDのアルファベットやサイズを調整する際の衝突確率を表示します。
  • nanoid-dictionaryはcustomAlphabetで使用する一般的なアルファベットを提供します。
  • nanoid-goodはIDに不適切な単語が含まれていないことを確認します。

File: README.ko.md

Nano ID

English | 日本語 | Русский | 简体中文 | Bahasa Indonesia | 한국어 | العربية

JavaScript를 위한 가볍고 안전하며 URL 친화적인 고유 String ID 생성기

“대단한 레벨의 무의미한 완벽주의,
경의를 표하지 않을 수 없습니다”

  • 가볍습니다. 118 bytes (minified 및 brotli 적용 후). 다른 의존성이 없습니다.
    Size Limit 의 기능으로 컨트롤합니다.
  • 빠릅니다. 네이티브 crypto.randomUUID() 보다 50% 더 빠릅니다.
  • 안전합니다. 하드웨어의 랜덤 생성기를 사용합니다. 클러스터에서 사용할 수 있습니다.
  • 짧은 ID를 생성합니다. UUID와는 다르게 대소문자를 모두 사용하여 키를 생성하므로, 36 byte를 차지하는 UUID와 다르게 21 byte만으로도 고유 아이디를 생성할 수 있습니다.
    So ID size was reduced from 36 to 21 symbols.
  • 이식이 쉽습니다. Nano ID 는 20개 이상의 언어로 포팅되었습니다 다른 언어들.
js
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

  Nano ID는 **Evil Martians**가 만들었습니다. 저희는 개발자 도구, AI, 사이버 보안 스타트업을 위한 미국의 디자인 및 엔지니어링 컨설팅 회사입니다.


목차

UUID와 비교

Nano ID 는 (랜덤 기반의) UUID v4와 비교할 수 있습니다.
아이디로 생성되는 랜덤 비트의 수가 유사하여
(Nano ID는 126개, UUID는 122개), 동일한 아이디가 생성될 수 있는 충돌 확률도 비슷합니다:

10억 분의 1의 확률로 충돌이 발생하기 위해서는
103조 번의 v4 ID가 생성되어야 합니다.

Nano ID와 UUID v4에는 두 가지의 주요한 차이점이 있습니다:

  1. Nano ID는 대문자를 사용합니다. 그래서 유사한 개수의 랜덤 값을 36개가 아닌 21개의 문자로 나타낼 수 있습니다.
  2. Nano ID는 crypto.randomUUID 및 uuid/v4 보다 빠릅니다.

벤치마크

rust
$ node ./test/benchmark.js
nope-id                 20,386,830 ops/sec
nanoid                  20,434,827 ops/sec
customAlphabet          20,544,476 ops/sec
crypto.randomUUID       12,865,759 ops/sec
uuid v4                  7,930,104 ops/sec
@napi-rs/uuid            5,573,171 ops/sec
uid/secure               6,308,267 ops/sec
@lukeed/uuid             5,278,597 ops/sec
nanoid for browser         311,497 ops/sec
secure-random-string       301,667 ops/sec
uid-safe.sync              297,815 ops/sec

Non-secure:
uid                     20,286,757 ops/sec
nanoid/non-secure        2,397,594 ops/sec
rndm                     2,445,462 ops/sec

보안

랜덤 생성기에 대한 설명은 다음 기사를 참고하세요:
Secure random values (in Node.js)

  • 예측불가성. 안전하지 않은 Math.random()를 사용하는 대신, Nano ID는
    Node.js에서 제공하는 crypto 모듈과 브라우저의 Web Crypto API를 사용합니다.
    이 모듈들은 예측이 불가능한 하드웨어 레벨의 랜덤 생성기입니다.

  • 균일성. random % alphabet 는 랜덤 아이디 생성기를 만들때 흔히들 하는 실수입니다.
    이 경우 분포(수학)가 일정하지 않게 되며, 일부 기호들은 다른 기호들보다 사용될 확률이 낮아집니다.
    이로 인해 브루트포스를 사용한 시도의 횟수를 줄일 수 있는 결과를 가져옵니다.
    Nano ID는 이보다 더 좋은 알고리즘을 사용하며, 균일성 테스트를 수행하였습니다.

  • 문서화: Nano ID의 모든것이 코드에 문서화되어있습니다. 소스 코드에서 코멘트를 확인하세요.

  • 취약점: 보안 취약점에 대한 리포트는 아래 링크를 사용해주세요.
    Tidelift security contact.
    Tidelift에서 취약점에 대한 수정 및 알림등을 도와줄 수 있습니다.

설치

bash
npm install nanoid

JSR

JSR 은 npm을 대체할 수 있는 오픈 거버넌스이며 npm과 달리 현재 활발히 개발중에 있습니다.

bash
npx jsr add @sitnik/nanoid

Node.js, Deno, Bun 등에서 사용할 수 있습니다.

js
// 모든 `nanoid` import를 `@sitnik/nanoid`로 변경합니다
import { nanoid } from '@sitnik/nanoid'

Deno 사용시에는 deno add jsr:@sitnik/nanoid 명령어로 설치하고
jsr:@sitnik/nanoid로 import 합니다.

CDN

빠른 적용을 위해 CDN에서 Nano ID를 가져올 수 있습니다.
하지만 로딩 성능이 늦어지므로 프로덕션에서는 사용하는 것을 추천하지 않습니다.

js
import { nanoid } from 'https://cdn.jsdelivr.net/npm/nanoid/nanoid.js'

API

기본적으로 Nano ID는 URL에 친화적인 기호들을 사용하여 21자리의 랜덤한 문자열을 생성합니다.
(이들은 UUID v4와 유사한 중복생성 확률을 가집니다)

js
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

생성되는 랜덤 아이디의 크기를 줄이고 싶으면 파라미터로 해당 길이 값을 넣어주면 됩니다.
(이렇게 하면 중복 생성이 발생할 확률도 올라갑니다)

js
nanoid(10) //=> "IRFa-VaY2b"

아래의 아이디 중복확률 계산기로 여러분의 아이디가 얼마나 안전한지 확인해보세요.

사용자 커스텀 문자열 이나
사용자가 만든 랜덤 생성기 를 사용할 수도 있습니다.

사용자 커스텀 문자열

customAlphabet 함수를 사용하면 지정된 문자열 내에서 지정된 개수로 이루어진
랜덤 아이디를 생성할 수 있는 nanoid 함수를 만들 수 있습니다

js
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
model.id = nanoid() //=> "4f90d13a42"
js
import { customAlphabet } from 'nanoid/non-secure'
const nanoid = customAlphabet('1234567890abcdef', 10)
user.id = nanoid()

아이디 충돌 확률 계산기를 사용하여 여러분이 지정한 문자와 사이즈에 대한 중복 생성 확률을 확인해보세요.
nanoid-dictionary 에서 어떤 문자열을 사용할 수 있는지에 대한 옵션을 확인할 수 있습니다.

커스텀 문자열은 256개 이하의 개수를 가져야 합니다.
그 외의 경우 내부의 생성 알고리즘의 보안성을 보장할 수 없습니다.

기본 사이즈를 지정한 후에, 새로 만들어진 함수를 부를 때 생성할 문자열의 개수를 다시 지정하는 것도 가능합니다

js
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
model.id = nanoid(5) //=> "f01a2"

사용자 지정 랜덤 바이트 생성기

customRandom 함수를 사용하면 nanoid에서 사용할 문자열과 알고리즘을 지정할 수 있습니다.

아래 예시는 시드 값을 기반으로 하는 랜덤 생성기를 사용하였습니다.

js
import { customRandom } from 'nanoid'

const rng = seedrandom(seed)
const nanoid = customRandom('abcdef', 10, size => {
  return new Uint8Array(size).map(() => 256 * rng())
})

nanoid() //=> "fbaefaadeb"

콜백 함수 random 는 반드시 배열의 크기를 받을 수 있어야 하며, 랜덤 숫자로 이루어진 배열을 리턴해야 합니다.

URL 친화적인 기호들을 사용하여 customRandom 을 실행하려면,
urlAlphabet을 사용해 기본 문자셋을 가져올 수 있습니다.

js
const { customRandom, urlAlphabet } = require('nanoid')
const nanoid = customRandom(urlAlphabet, 10, random)

참고로, Nano ID 버전이 변경됨에 따라 랜덤 생성기의 호출 시퀀스가 변경될 수 있습니다.
시드기반 생성기를 사용하는 경우 동일한 결과가 나오는 것을 보장할 수 없습니다.

Non-Secure

Nano ID는 보안과 낮은 충돌 확률을 위해 하드웨어 랜덤 바이트 생성기를 사용합니다.
만약 보안이 중요하지 않다면 하드웨어 랜덤 생성기를 사용하지 않도록 설정할 수 있습니다.

js
import { nanoid } from 'nanoid/non-secure'
const id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ"

단, non-secure 버전은 secure 버전보다 느리다는 점에 유의하세요.
꼭 필요한 경우에만 사용하세요.

사용법

React

React에서 key props에 Nano ID를 사용하는 것은 좋지 않습니다.
이 값은 렌더링 될 때마다 동일한 값을 가지고 있어야 합니다.

jsx
function Todos({ todos }) {
  return (
    
      {todos.map(todo => (
        <li key={nanoid()}>
          {' '}
          /* 절대 하지 마세요 */
          {todo.text}
        </li>
      ))}
    
  )
}

랜덤값보다 리스트 내에서 가져올 수 있는 값을 사용하여 안정된 값을 키 값으로 사용하는 것이 좋습니다.

jsx
const todoItems = todos.map(todo => <li key={todo.id}>{todo.text}</li>)

key 값으로 사용할 적절한 값이 없는 경우에도 nanoid()를 사용하기 보다는 인덱스 값을 사용하세요:

jsx
const todoItems = todos.map((text, index) => (
  <li key={index}>
    {' '}
    /* 추천되는 방식은 아니지만 nanoid()를 쓰는것 보단 낫습니다 */
    {text}
  </li>
))

랜덤한 아이디를 생성하여 HTML 요소간의 연결 (label과 input 등)에 사용하는 경우에는
React 18에서 추가된 useId 를 추천합니다.

React Native

React Native에는 내장된 랜덤 생성기가 존재하지 않습니다.
아래의 폴리필을 사용하면 순수 React Native와 Expo(39버전 이상) 환경에서
Nano ID를 사용할 수 있습니다.

  1. react-native-get-random-values 문서를 확인하고 설치합니다
  2. Nano ID를 import하기 전에 이 패키지를 import 해야 합니다.
js
import 'react-native-get-random-values'
import { nanoid } from 'nanoid'

PouchDB 및 CouchDB

PouchDB와 CouchDB에서는 ID 값을 _로 시작할 수 없습니다.
Nano ID는 기본적으로 _를 맨 앞에 붙일 수 있기 때문에,
이 문제를 해결하기 위해 접두어 (prefix)가 필요합니다.

아래와 같이 접두어를 붙여서 사용합니다.

js
db.put({
  _id: 'id' + nanoid(),
  …
})

CLI

터미널에서 npx nanoid 명령어를 입력하면 고유 ID를 생성할 수 있습니다.
Node.js가 시스템에 설치되어있어야 하며, Nano ID는 미리 설치되어있지 않아도 됩니다.

sh
$ npx nanoid
npx: installed 1 in 0.63s
LZfXLFzPPR4NNrgjlWDxn

생성할 아이디의 길이를 변경하려면 --size (or -s) 옵션을 붙여줍니다:

sh
$ npx nanoid --size 10
L3til0JS4z

사용자 커스텀 문자열을 사용하려면 --alphabet (or -a) 옵션을 사용합니다
(이 때 --size도 같이 사용해야 합니다):

sh
$ npx nanoid --alphabet abc --size 15
bccbcabaabaccab

TypeScript

Nano ID는 생성된 문자열을 TypeScript의 순수 string이 아닌 타입에도 할당할 수 있습니다.
예를 들어 아래와 같이 가능합니다:

ts
declare const userIdBrand: unique symbol
type UserId = string & { [userIdBrand]: true }

// 명시적으로 타입 파라미터를 사용:
mockUser(nanoid())

interface User {
  id: UserId
  name: string
}

const user: User = {
  // 자동으로 UserId 타입으로 캐스팅됨:
  id: nanoid(),
  name: 'Alice'
}

다른 언어들

Nano ID는 다양한 언어로 포팅되었습니다. 클라이언트/서버에 관계없이 아래의 다양한 포팅된 버전들을 사용할 수 있습니다.

이 외의 환경에서는 CLI를 사용하여 터미널 환경에서 랜덤 아이디를 생성할 수 있습니다.

도구

  • ID 사이즈 계산기는 문자열과 생성 사이즈를 변경한 경우 중복된 아이디가 생성될 수 있는 충돌 확률을 알려줍니다.
  • customAlphabet에서 사용할 수 있는 일반적인 문자열들을 nanoid-dictionary로 찾아볼 수 있습니다.
  • 생성된 ID에 이상한 단어가 들어가는 것을 방지하려면 nanoid-good를 사용할 수 있습니다.

File: README.ru.md

Nano ID

English | 日本語 | Русский | 简体中文 | Bahasa Indonesia | 한국어 | العربية

Генератор уникальных ID для JavaScript — лёгкий, безопасный,
ID можно применять в URL.

«Поразительный уровень бессмысленного перфекционизма,
который просто невозможно не уважать»

  • Лёгкий. 118 байт (после минификации и Brotli). Без зависимостей.
    Size Limit следит за размером.
  • Быстрый. На 50% быстрее нативного crypto.randomUUID().
  • Безопасный. Использует аппаратный генератор случайных чисел.
    Можно использовать в кластерах машин.
  • Короткие ID. Используется больший алфавит, чем у UUID (A-Za-z0-9_-).
    Поэтому длина ID уменьшена с 36 до 21 символа.
  • Работает везде. Nano ID уже портировали
    на 20 языков программирования.
js
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

Поддерживает современные браузеры, IE (с Babel), Node.js и React Native.


  Nano ID сделан в Злых марсианах, американском консалтинге по дизайну и разработке для стартапов в области инструментов разработки, ИИ и кибербезопасности.


Оглавление

Сравнение с UUID

Nano ID похож на UUID v4 (случайный).
У них сравнимое число битов случайности в ID (126 у Nano ID против 122 у UUID),
поэтому они обладают похожей вероятностью возникновения коллизий
(повторной генерации ранее выданных ID):

Чтобы вероятность повтора приблизилась к 1 на миллиард,
нужно сгенерировать 103 триллиона ID.

Но между ними есть 2 важных отличия:

  1. Nano ID использует более широкий алфавит, и сравнимое количество
    битов случайности будут упакованы в более короткую строку
    (21 символ, против 36 у UUID).
  2. Nano ID быстрее, чем crypto.randomUUID и uuid/v4.

Сравнение производительности

rust
$ node ./test/benchmark.js
nope-id                 20,386,830 ops/sec
nanoid                  20,434,827 ops/sec
customAlphabet          20,544,476 ops/sec
crypto.randomUUID       12,865,759 ops/sec
uuid v4                  7,930,104 ops/sec
@napi-rs/uuid            5,573,171 ops/sec
uid/secure               6,308,267 ops/sec
@lukeed/uuid             5,278,597 ops/sec
nanoid for browser         311,497 ops/sec
secure-random-string       301,667 ops/sec
uid-safe.sync              297,815 ops/sec

Non-secure:
uid                     20,286,757 ops/sec
nanoid/non-secure        2,397,594 ops/sec
rndm                     2,445,462 ops/sec

Безопасность

См. также хорошую статью о теориях генераторов случайных чисел:
Secure random values (in Node.js)

  • Непредсказуемость. Вместо предсказуемого Math.random(), Nano ID
    использует модуль crypto в Node.js и Web Crypto API в браузере.
    Эти модули дают доступ к аппаратному генератору случайных чисел.

  • Равномерность. Например, существует популярная ошибка random % alphabet,
    которую часто допускают при разработке генератора ID.
    Распределение вероятности для каждого символа может не быть одинаковым.
    Из-за неравномерности использования пространства алфавита, на перебор ID
    потребуется меньше времени, чем ожидается.
    Nano ID использует более совершенный алгоритм,
    а равномерность распределения символов покрыта тестами.

  • Документация: все хитрости Nano ID хорошо документированы — смотрите
    комментарии в исходниках.

  • Уязвимости: если вы нашли уязвимость в Nano ID, свяжитесь с
    командой безопасности Tidelift.
    Они проконтролируют исправление и проинформируют пользователей.

Подключение

bash
npm install nanoid

JSR

JSR это замена npm с открытым управлением
и активной разработкой (в отличие от npm).

bash
npx jsr add @sitnik/nanoid

Вы можете использовать пакет с JSR в Node.js, Deno, Bun.

js
// Replace `nanoid` to `@sitnik/nanoid` in all imports
import { nanoid } from '@sitnik/nanoid'

Для Deno установите через deno add jsr:@sitnik/nanoid
или импортируйте jsr:@sitnik/nanoid.

CDN

Для быстрого прототипирования вы можете подключить Nano ID с CDN без установки.
Не используйте этот способ на реальном сайте, так как он сильно бьёт
по скорости загрузки сайта.

js
import { nanoid } from 'https://cdn.jsdelivr.net/npm/nanoid/nanoid.js'

API

По умолчанию используются символы, безопасные для URL (A-Za-z0-9_-).
Длина ID по умолчанию — 21 символ
(чтобы вероятность коллизий была соизмеримой с UUID v4).

js
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

Функция также принимает необязательный аргумент, задающий длину ID:

js
nanoid(10) //=> "IRFa-VaY2b"

При изменении размера, всегда проверяйте риски
в нашем калькуляторе коллизий.

Смена алфавита или длины

Функция customAlphabet позволяет создать свою функцию nanoid
с нужным вам алфавитом и длиной ID.

js
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
user.id = nanoid() //=> "4f90d13a42"
js
import { customAlphabet } from 'nanoid/non-secure'
const nanoid = customAlphabet('1234567890abcdef', 10)
user.id = nanoid()

Не забудьте проверить риски коллизии вашего алфавита и длины
на нашем калькуляторе. nanoid-dictionary содержит много популярных
примеров альтернативных алфавитов.

Алфавит должен содержать ≤256 символов. Иначе мы не сможем гарантировать
непредсказуемость ID.

Длину ID можно менять не только в customAlphabet(), но и при вызове
генератора, который она вернёт:

js
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
model.id = nanoid(5) //=> "f01a2"

Смена генератора случайных чисел

Функция customRandom позволяет создать свою функцию nanoid со своими
генераторами случайных чисел, алфавитом и длинной ID.

Например, можно использовать генератор c seed для повторяемости тестов.

js
import { customRandom } from 'nanoid'

const rng = seedrandom(seed)
const nanoid = customRandom('abcdef', 10, size => {
  return new Uint8Array(size).map(() => 256 * rng())
})

nanoid() //=> "fbaefaadeb"

Функция в третьем аргументе customRandom должна принимать длину массива
и возвращать нужный массив со случайными числами

Если вы хотите заменить только генератор случайных чисел, но оставить
URL-совместимый алфавит, то стандартный алфавит доступен
в экспорте urlAlphabet.

js
const { customRandom, urlAlphabet } = require('nanoid')
const nanoid = customRandom(urlAlphabet, 10, random)

Небезопасный

Nano ID использует аппаратный генератор случайных чисел для
получения непредсказуемых ID и минимизации риска возникновения коллизий
(повторной генерации ранее выданных ID). Но если вам не требуется устойчивость
к подбору ID, то вы можете перейти на небезопасный генератор — это полезно
там, где нет доступа к API аппаратного генератора случайных чисел.

js
import { nanoid } from 'nanoid/non-secure'
const id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ"

Но учтите, что предсказуемость ID может быть использована для атаки на систему.
Кроме того, небезопасная версия работает медленнее безопасной —
используйте её, только если без неё не обойтись.

Руководство

React

Не используйте Nano ID для генерации свойства key в JSX. При каждом рендере
key будет разный, что плохо скажется на производительности.

jsx
function Todos({ todos }) {
  return (
    
      {todos.map(todo => (
        <li key={nanoid()}>
          {' '}
          /* НЕ ДЕЛАЙТЕ ТАК */
          {todo.text}
        </li>
      ))}
    
  )
}

Для связи `` и <label> лучше использовать useId,
который был добавлен в React 18.

React Native

React Native не имеет встроенного аппаратного генератора случайных чисел.
Полифил ниже работает в чистом React Native и в Expo начиная с версии 39.

  1. Прочитайте документацию react-native-get-random-values и установите его.
  2. Импортируйте эту библиотеку до импорта Nano ID.
js
import 'react-native-get-random-values'
import { nanoid } from 'nanoid'

PouchDB и CouchDB

В PouchDB и CouchDB, ID не могут начинаться с _. Добавьте к ID префикс,
так как иногда Nano ID может сгенерировать ID начинающийся с _.

Изменить стандартный ID можно через следующую опцию:

js
db.put({
  _id: 'id' + nanoid(),
  …
})

Терминал

Можно сгенерировать уникальный ID прямо из терминала, вызвав npx nanoid.
Для этого в системе должна быть только Node.js. npx сама скачает Nano ID,
если его нет в системе.

sh
$ npx nanoid
npx: installed 1 in 0.63s
LZfXLFzPPR4NNrgjlWDxn

Длину генерируемых ID можно передать в аргументе --size (или -s):

sh
$ npx nanoid --size 10
L3til0JS4z

Изменить алфавит можно при помощи аргумента --alphabet (ли -a)
(в этом случае --size обязателен):

sh
$ npx nanoid --alphabet abc --size 15
bccbcabaabaccab

TypeScript

Nano ID позволяет приводить сгенерированные строки к непрозрачным строкам в
TypeScript. Например:

ts
declare const userIdBrand: unique symbol
type UserId = string & { [userIdBrand]: true }

// Используйте явный параметр типа:
mockUser(nanoid())

interface User {
  id: UserId
  name: string
}

const user: User = {
  // Автоматически приводится к типу UserId:
  id: nanoid(),
  name: 'Alice'
}

Другие языки программирования

Nano ID был портирован на множество языков. Это полезно, чтобы сервер и клиент
генерировали ID по одной схеме.

Для остальных сред можно использовать Nano ID для терминала.

Инструменты

  • Калькулятор длины ID поможет подобрать оптимальную длину ID,
    в зависимости от частоты выдачи ID и нужной надёжности системы.
  • nanoid-dictionary с популярными алфавитами для customAlphabet.
  • nanoid-good гарантирует, что в случайном ID не будет матерных слов.

File: README.zh-CN.md

Nano ID

English | 日本語 | Русский | 简体中文 | Bahasa Indonesia | 한국어 | العربية

一个小巧、安全、URL友好、唯一的 JavaScript 字符串ID生成器。

“一个惊人的无意义的完美主义水平,这简直让人无法不敬佩。”

  • 小巧. 118字节 (经过压缩和Brotli处理)。没有依赖。Size Limit 控制大小。
  • 快速. 比原生 crypto.randomUUID() 快 50%。
  • 安全. 它使用硬件随机生成器。可在集群中使用。
  • 紧凑. 它使用比 UUID(A-Za-z0-9_-)更大的字母表。因此,ID 大小从36个符号减少到21个符号。
  • 可移植. Nano ID 已被移植到 20种编程语言。
js
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

支持现代浏览器、IE [需使用 Babel]、Node.js 和 React Native。


  Nano ID 由 Evil Martians 开发,我们是一家美国的设计与工程咨询公司,专注于开发者工具、AI 和网络安全领域的初创公司。


目录

与 UUID 的比较

Nano ID 与 UUID v4 (基于随机数) 相当。
它们在 ID 中有相似数量的随机位
(Nano ID 为126,UUID 为122),因此它们的碰撞概率相似::

要想有十亿分之一的重复机会,
必须产生103万亿个版本4的ID.

Nano ID 和 UUID v4之间有两个主要区别:

  1. Nano ID 使用更大的字母表,所以类似数量的随机位
    被包装在21个符号中,而不是36个。
  2. Nano ID 比 crypto.randomUUID 和 uuid/v4 更快。

基准值

rust
$ node ./test/benchmark.js
nope-id                 20,386,830 ops/sec
nanoid                  20,434,827 ops/sec
customAlphabet          20,544,476 ops/sec
crypto.randomUUID       12,865,759 ops/sec
uuid v4                  7,930,104 ops/sec
@napi-rs/uuid            5,573,171 ops/sec
uid/secure               6,308,267 ops/sec
@lukeed/uuid             5,278,597 ops/sec
nanoid for browser         311,497 ops/sec
secure-random-string       301,667 ops/sec
uid-safe.sync              297,815 ops/sec

Non-secure:
uid                     20,286,757 ops/sec
nanoid/non-secure        2,397,594 ops/sec
rndm                     2,445,462 ops/sec

安全性

请看一篇关于随机生成器理论的好文章:
安全的随机值 (在 Node.js 中)

  • 不可预测性. 不使用不安全的 Math.random(), Nano ID
    使用 Node.js 的 crypto 模块和浏览器的 Web Crypto API。
    这些模块使用不可预测的硬件随机生成器。

  • 统一性. random % alphabet 是编写ID生成器时常犯的一个错误。
    这样做会导致分布不均匀; 一些符号出现的机会较其他符号低。因此,在暴力破解时,尝试的次数会减少。
    Nano ID 使用了一种 更好的算法,并进行了一致性测试。

  • 有据可查: 所有的 Nano ID 的行为都有记录。
    见 源代码 中的注释。

  • 漏洞: 报告安全漏洞,请使用
    安全联系人 Tidelift.
    Tidelift 将协调修复和披露。

安装

bash
npm install nanoid

想要快速上手尝试,你可以从 CDN 加载 Nano ID。但是,它不建议
在生产中使用,因为它的加载性能较低。

js
import { nanoid } from 'https://cdn.jsdelivr.net/npm/nanoid/nanoid.js'

API

默认情况下,Nano ID 使用 URL 友好的符号(A-Za-z0-9_-)并返回一个
有21个字符(类似 UUID v4 的碰撞概率)的 ID。

js
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

如果你想要减小 ID 大小(但是会增加碰撞概率),
可以将大小作为参数传递

js
nanoid(10) //=> "IRFa-VaY2b"

别忘了在我们的 ID 碰撞概率 计算器中检查你的 ID 大小的安全性。

您也可以使用 自定义字母表
或者是 自定义生成器.

自定义字母或大小

customAlphabet 返回一个函数,允许您使用自定义字母表和ID大小创建 nanoid。

js
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
model.id = nanoid() //=> "4f90d13a42"
js
import { customAlphabet } from 'nanoid/non-secure'
const nanoid = customAlphabet('1234567890abcdef', 10)
user.id = nanoid()

在我们的 ID 碰撞概率 计算器中检查您的自定义字母表和 ID 大小的安全性。
查看 nanoid-dictionary 中的选项以获取更多字母表。

字母表必须包含256个或更少的符号。
否则,无法保证内部生成器算法的安全性。

除了设置默认大小外,您还可以在调用函数时更改ID大小:

js
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
model.id = nanoid(5) //=> "f01a2"

自定义随机字节生成器

customRandom 允许您创建一个 nanoid 并替换字母表
和默认的随机字节生成器。

在此示例中,使用基于种子的生成器:

js
import { customRandom } from 'nanoid'

const rng = seedrandom(seed)
const nanoid = customRandom('abcdef', 10, size => {
  return new Uint8Array(size).map(() => 256 * rng())
})

nanoid() //=> "fbaefaadeb"

random 回调必须接受数组大小并返回随机数的数组。

如果要使用与 customRandom 相同的URL友好符号,
您可以使用 urlAlphabet 获取默认字母表。

js
const { customRandom, urlAlphabet } = require('nanoid')
const nanoid = customRandom(urlAlphabet, 10, random)

请注意,在Nano ID的不同版本之间,我们可能会更改随机生成器的调用顺序。如果您正在使用基于种子的生成器,我们不能保证相同的结果。

不安全

Nano ID 使用硬件随机字节生成以提供安全性和较低的碰撞概率。如果您对安全性不太担心,您可以在没有硬件随机生成器的环境中使用它

js
import { nanoid } from 'nanoid/non-secure'
const id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ"

请注意,非安全版本比安全版本更慢,请仅在必要时使用。

用法

React

目前还没有将 nanoid 用于 React key prop 的正确方法
因为它在不同的渲染中应该是一致的。

jsx
function Todos({ todos }) {
  return (
    
      {todos.map(todo => (
        <li key={nanoid()}>
          {' '}
          /* 不要这样做 */
          {todo.text}
        </li>
      ))}
    
  )
}

您应该尝试在列表项中找到稳定的 id。

jsx
const todoItems = todos.map(todo => <li key={todo.id}>{todo.text}</li>)

如果您没有稳定的 ID,您最好使用索引作为 键 而不是 nanoid():

jsx
const todoItems = todos.map((text, index) => (
  <li key={index}>
    {' '}
    /* 仍然不推荐,但优于 nanoid()。 仅当项目没有稳定ID时才执行此操作。 */
    {text}
  </li>
))

如果您只需要随机 ID 来将元素(如标签和输入字段)链接在一起,建议使用 useId。该钩子在 React 18 中添加。

React Native

React Native 没有内置的随机生成器。以下polyfill适用于纯 React Native 和 Expo,从39.x版本开始生效。

  1. 检查 react-native-get-random-values 文档并安装它。
  2. 在 Nano ID 之前导入它。
js
import 'react-native-get-random-values'
import { nanoid } from 'nanoid'

PouchDB and CouchDB

在 PouchDB 和 CouchDB 中,ID 不能以下划线 _ 开头。
需要一个前缀来防止这个问题,因为 Nano ID 可能在默认情况下使用 _ 作为 ID 的开头。
在默认情况下,在 ID 的开头使用 _。

用下面的选项覆盖默认的 ID。

js
db.put({
  _id: 'id' + nanoid(),
  …
})

CLI

你可以通过调用 npx nanoid 在终端获得唯一的 ID。你只需要
在系统中安装了 Node.js。你不需要把 Nano ID 安装在任何地方。

sh
$ npx nanoid
npx: installed 1 in 0.63s
LZfXLFzPPR4NNrgjlWDxn

生成的ID的大小可以使用 --size(或 -s )选项指定:

sh
$ npx nanoid --size 10
L3til0JS4z

可以使用 --alphabet(或 -a )选项指定自定义字母表(请注意,这种情况下需要 --size 选项)。

sh
$ npx nanoid --alphabet abc --size 15
bccbcabaabaccab

TypeScript

Nano ID 允许将生成的字符串转换为 TypeScript 中的不透明字符串。 例如:

ts
declare const userIdBrand: unique symbol
type UserId = string & { [userIdBrand]: true }

// 使用显式类型参数:
mockUser(nanoid())

interface User {
  id: UserId
  name: string
}

const user: User = {
  // 自动转换为 UserId:
  id: nanoid(),
  name: 'Alice'
}

其他编程语言

Nano ID 已被移植到许多语言。 你可以使用下面这些移植,获取在客户端和服务器端相同的ID生成器。

此外,CLI 还可用于从命令行生成 ID。

工具