NanoID - 輕量、安全的 Unique ID 生成器

Nano ID

一個(gè)小巧、安全、URL友好、唯一的 JavaScript 字符串 ID 生成器。

  • 小巧:130 bytes (已壓縮和 gzipped), 沒有依賴,Size Limit 控制大小;
  • 快速:它比 UUID 快 60%;
  • 安全:它使用加密的強(qiáng)隨機(jī) API,可在集群中使用;
  • 緊湊:它使用比 UUID(A-Za-z0-9_-)更大的字母表,因此,ID 大小從 36 個(gè)符號(hào)減少到 21 個(gè)符號(hào);
  • 易用:Nano ID 已被移植到 20種編程語言。
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"

支持現(xiàn)代瀏覽器、IE 使用 Babel、Node.js 和 React Native。

與 UUID 的比較

Nano ID 與 UUID v4 (基于隨機(jī)) 相當(dāng)。它們?cè)?ID 中有相似數(shù)量的隨機(jī)位(Nano ID 為126,UUID 為122),因此它們的沖突概率相似::

要想有十億分之一的重復(fù)機(jī)會(huì),必須產(chǎn)生 103萬億 個(gè)版本4的 ID 。

Nano ID 和 UUID v4之間有三個(gè)主要區(qū)別:

  1. Nano ID 使用更大的字母表,所以類似數(shù)量的隨機(jī)位被包裝在 21 個(gè)符號(hào)中,而不是36個(gè)。
  2. Nano ID 代碼比 uuid/v4 包少 4 倍:130 字節(jié)而不是 483 字節(jié).
  3. 由于內(nèi)存分配的技巧,Nano ID 比 UUID 快 60%。

基準(zhǔn)值

$ node ./test/benchmark.js
crypto.randomUUID         25,603,857 ops/sec
@napi-rs/uuid              9,973,819 ops/sec
uid/secure                 8,234,798 ops/sec
@lukeed/uuid               7,464,706 ops/sec
nanoid                     5,616,592 ops/sec
customAlphabet             3,115,207 ops/sec
uuid v4                    1,535,753 ops/sec
secure-random-string         388,226 ops/sec
uid-safe.sync                363,489 ops/sec
cuid                         187,343 ops/sec
shortid                       45,758 ops/sec

Async:
nanoid/async                  96,094 ops/sec
async customAlphabet          97,184 ops/sec
async secure-random-string    92,794 ops/sec
uid-safe                      90,684 ops/sec

Non-secure:
uid                       67,376,692 ops/sec
nanoid/non-secure          2,849,639 ops/sec
rndm                       2,674,806 ops/sec

測(cè)試配置: ThinkPad X1 Carbon Gen 9, Fedora 34, Node.js 16.10.

安裝

npm install --save nanoid

Nano ID 提供 ES 模塊:

import { nanoid } from 'nanoid'

API

Nano ID 有 3 個(gè) API:正常(阻塞)、異步、和不安全。默認(rèn)情況下,Nano ID 使用 URL 友好的符號(hào)(A-Za-z0-9_-)并返回一個(gè)有21個(gè)字符(類似 UUID v4 的沖突概率)的 ID 。

阻塞

使用 Nano ID 最安全、最簡(jiǎn)單的方法。在極少數(shù)情況下,噪聲收集時(shí)可能會(huì)阻止 CPU 執(zhí)行其他工作用于硬件隨機(jī)發(fā)生器。

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

如果你想要減小 ID size(但是會(huì)增加沖突概率),可以將 size 作為參數(shù)傳遞。

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

異步

import { nanoid } from 'nanoid/async'

async function createUser () {
  user.id = await nanoid()
}

不安全

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

自定義字母或大小

customAlphabet 允許您使用自己的字母表創(chuàng)建 nanoid 和 ID size。

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

自定義隨機(jī)字節(jié)生成器

customRandom 允許您創(chuàng)建一個(gè) nanoid 并替換字母表和默認(rèn)的隨機(jī)字節(jié)生成器。

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

import { customRandom } from 'nanoid'

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

nanoid() //=> "fbaefaadeb"

random 回調(diào)必須接受數(shù)組大小并返回隨機(jī)數(shù)的數(shù)組。如果要使用與 customRandom 相同的URL友好符號(hào), 你可以使用 urlAlphabet 獲取默認(rèn)字母表。

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

異步和非安全 API 不適用于 customRandom。

用法

React

目前還沒有將 nanoid 用于 React key prop 的正確方法
因?yàn)樗诓煌匿秩局袘?yīng)該是一致的。

function Todos({todos}) {
  return (
    <ul>
      {todos.map(todo => (
        <li key={nanoid()}> /* 不要這樣做 */
          {todo.text}
        </li>
      ))}
    </ul>
  )
}

您應(yīng)該嘗試在列表項(xiàng)中找到穩(wěn)定的 id。

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

如果您沒有穩(wěn)定的 ID,您最好使用索引作為 而不是 nanoid()

const todoItems = todos.map((text, index) =>
  <li key={index}> /* 仍然不推薦,但優(yōu)于 nanoid()。
                      僅當(dāng)項(xiàng)目沒有穩(wěn)定ID時(shí)才執(zhí)行此操作。 */
    {text}
  </li>
)

React Native

React Native 沒有內(nèi)置的隨機(jī)生成器。下面的 polyfill 適用于普通 React Native 和從 39.x 開始的 Expo。

  1. 檢查 react-native-get-random-values 文檔并安裝它。
  2. 在 Nano ID 之前導(dǎo)入它。
import 'react-native-get-random-values'
import { nanoid } from 'nanoid'

PouchDB and CouchDB

在 PouchDB 和 CouchDB 中,ID 不能以下劃線 _ 開頭。需要一個(gè)前綴來防止這個(gè)問題,因?yàn)?Nano ID 可能在默認(rèn)情況下使用 _ 作為 ID 的開頭。在默認(rèn)情況下,在 ID 的開頭使用 _。

用下面的選項(xiàng)覆蓋默認(rèn)的 ID。

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

CLI

可以通過調(diào)用 npx nanoid 在終端獲得唯一的 ID。

$ npx nanoid
npx: installed 1 in 0.63s
LZfXLFzPPR4NNrgjlWDxn

如果你想改變字母或 ID size,應(yīng)該使用 nanoid-cli

其他編程語言

Nano ID 已被移植到許多語言。 你可以使用下面這些移植,獲取在客戶端和服務(wù)器端相同的ID生成器。

其他方式生成 ID

new Date().getTime().toString(36).concat(performance.now().toString(), Math.random().toString()).replace(/\./g,"")

相關(guān)討論:https://gist.github.com/gordonbrander/2230317

工具

相關(guān)資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容