@hoseki-inc/nanoid
v5.0.10
Published
A tiny (116 bytes), secure URL-friendly unique string ID generator
Downloads
307
Readme
Nano ID
English | Русский | 简体中文 | Bahasa Indonesia
一个小巧、安全、URL友好、唯一的 JavaScript 字符串ID生成器。
“一个惊人的无意义的完美主义水平,这简直让人无法不敬佩。”
- 小巧. 116字节 (经过压缩和Brotli处理)。没有依赖。Size Limit 控制大小。
- 安全. 它使用硬件随机生成器。可在集群中使用。
- 紧凑. 它使用比 UUID(
A-Za-z0-9_-
)更大的字母表。因此,ID 大小从36个符号减少到21个符号。 - 可移植. Nano ID 已被移植到 20种编程语言。
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"
支持现代浏览器、IE [需使用 Babel]、Node.js 和 React Native。
Made in Evil Martians, product consulting for developer tools.
目录
与 UUID 的比较
Nano ID 与 UUID v4 (基于随机数) 相当。 它们在 ID 中有相似数量的随机位 (Nano ID 为126,UUID 为122),因此它们的碰撞概率相似::
要想有十亿分之一的重复机会, 必须产生103万亿个版本4的ID.
Nano ID 和 UUID v4之间有两个主要区别:
- Nano ID 使用更大的字母表,所以类似数量的随机位 被包装在21个符号中,而不是36个。
- Nano ID 代码比
uuid/v4
包少 4倍: 130字节而不是423字节.
基准值
$ node ./test/benchmark.js
crypto.randomUUID 28,398,328 ops/sec
uuid v4 10,254,199 ops/sec
@napi-rs/uuid 15,110,625 ops/sec
uid/secure 10,388,842 ops/sec
@lukeed/uuid 8,914,507 ops/sec
nanoid 7,484,029 ops/sec
customAlphabet 4,867,017 ops/sec
nanoid for browser 609,426 ops/sec
secure-random-string 539,080 ops/sec
uid-safe.sync 533,944 ops/sec
shortid 59,609 ops/sec
Non-secure:
uid 95,579,977 ops/sec
nanoid/non-secure 3,999,766 ops/sec
rndm 3,981,914 ops/sec
测试配置: Framework 13 7840U, Fedora 39, Node.js 21.6.
安全性
请看一篇关于随机生成器理论的好文章: 安全的随机值 (在 Node.js 中)
不可预测性. 不使用不安全的
Math.random()
, Nano ID 使用 Node.js 的crypto
模块和浏览器的 Web Crypto API。 这些模块使用不可预测的硬件随机生成器。统一性.
random % alphabet
是编写ID生成器时常犯的一个错误。 这样做会导致分布不均匀; 一些符号出现的机会较其他符号低。因此,在暴力破解时,尝试的次数会减少。 Nano ID 使用了一种 更好的算法,并进行了一致性测试。有据可查: 所有的 Nano ID 的行为都有记录。 见 源代码 中的注释。
漏洞: 报告安全漏洞,请使用 安全联系人 Tidelift. Tidelift 将协调修复和披露。
安装
npm install nanoid
Nano ID 5 仅适用于 ESM 项目、测试或 Node.js 脚本。 对于 CommonJS,您需要 Nano ID 3.x(我们仍然支持它):
npm install nanoid@3
想要快速上手尝试,你可以从 CDN 加载 Nano ID。但是,它不建议 在生产中使用,因为它的加载性能较低。
import { nanoid } from 'https://cdn.jsdelivr.net/npm/nanoid/nanoid.js'
API
Nano ID 有2个 API:正常(阻塞),和不安全。
默认情况下,Nano ID 使用 URL 友好的符号(A-Za-z0-9_-
)并返回一个
有21个字符(类似 UUID v4 的碰撞概率)的 ID。
阻塞
使用 Nano ID 最安全、最简单的方法
在极少数情况下,当收集硬件随机生成器的噪声时,可能会阻塞CPU,导致无法进行其他工作。
import { nanoid } from 'nanoid'
model.id = nanoid() //=> "V1StGXR8_Z5jdHi6B-myT"
如果你想要减小 ID 大小(但是会增加碰撞概率), 可以将大小作为参数传递
nanoid(10) //=> "IRFa-VaY2b"
别忘了在我们的 ID 碰撞概率 计算器中检查你的 ID 大小的安全性。
不安全
默认情况下,Nano ID 使用硬件随机字节生成以提供安全性和较低的碰撞概率。如果您对安全性不太担心,您可以在没有硬件随机生成器的环境中使用它
import { nanoid } from 'nanoid/non-secure'
const id = nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ"
自定义字母或大小
customAlphabet
返回一个函数,允许您使用自定义字母表和ID大小创建 nanoid
。
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
model.id = nanoid() //=> "4f90d13a42"
import { customAlphabet } from 'nanoid/non-secure'
const nanoid = customAlphabet('1234567890abcdef', 10)
user.id = nanoid()
在我们的 ID 碰撞概率 计算器中检查您的自定义字母表和 ID 大小的安全性。
查看 nanoid-dictionary
中的选项以获取更多字母表。
字母表必须包含256个或更少的符号。 否则,无法保证内部生成器算法的安全性。
除了设置默认大小外,您还可以在调用函数时更改ID大小:
import { customAlphabet } from 'nanoid'
const nanoid = customAlphabet('1234567890abcdef', 10)
model.id = nanoid(5) //=> "f01a2"
自定义随机字节生成器
customRandom
允许您创建一个 nanoid
并替换字母表
和默认的随机字节生成器。
在此示例中,使用基于种子的生成器:
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
获取默认字母表。
const { customRandom, urlAlphabet } = require('nanoid')
const nanoid = customRandom(urlAlphabet, 10, random)
请注意,在Nano ID的不同版本之间,我们可能会更改随机生成器的调用顺序。如果您正在使用基于种子的生成器,我们不能保证相同的结果。
用法
React
目前还没有将 nanoid 用于 React key
prop 的正确方法
因为它在不同的渲染中应该是一致的。
function Todos({todos}) {
return (
<ul>
{todos.map(todo => (
<li key={nanoid()}> /* 不要这样做 */
{todo.text}
</li>
))}
</ul>
)
}
您应该尝试在列表项中找到稳定的 id。
const todoItems = todos.map((todo) =>
<li key={todo.id}>
{todo.text}
</li>
)
如果您没有稳定的 ID,您最好使用索引作为 键
而不是 nanoid()
:
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版本开始生效。
- 检查
react-native-get-random-values
文档并安装它。 - 在 Nano ID 之前导入它。
import 'react-native-get-random-values'
import { nanoid } from 'nanoid'
PouchDB and CouchDB
在 PouchDB 和 CouchDB 中,ID 不能以下划线 _
开头。
需要一个前缀来防止这个问题,因为 Nano ID 可能在默认情况下使用 _
作为 ID 的开头。
在默认情况下,在 ID 的开头使用 _
。
用下面的选项覆盖默认的 ID。
db.put({
_id: 'id' + nanoid(),
…
})
Web Workers
Web Workers 无法访问安全的随机生成器.
当ID应该是不可预测的时候,安全性对ID很重要。 例如,在 "按 URL 访问"的链接生成中。 如果你不需要不可预测的 ID,但你需要使用 Web Workers。 你可以使用非安全的 ID 生成器。
import { nanoid } from 'nanoid/non-secure'
nanoid() //=> "Uakgb_J5m9g-0JDMbcJqLJ"
注意:非安全的ID更容易受到碰撞攻击。
CLI
你可以通过调用 npx nanoid
在终端获得唯一的 ID。你只需要
在系统中安装了 Node.js。你不需要把 Nano ID 安装在任何地方。
$ npx nanoid
npx: installed 1 in 0.63s
LZfXLFzPPR4NNrgjlWDxn
生成的ID的大小可以使用 --size
(或 -s
)选项指定:
$ npx nanoid --size 10
L3til0JS4z
可以使用 --alphabet
(或 -a
)选项指定自定义字母表(请注意,这种情况下需要 --size
选项)。
$ npx nanoid --alphabet abc --size 15
bccbcabaabaccab
其他编程语言
Nano ID 已被移植到许多语言。 你可以使用下面这些移植,获取在客户端和服务器端相同的ID生成器。
- C#
- C++
- Clojure and ClojureScript
- ColdFusion/CFML
- Crystal
- Dart & Flutter
- Deno
- Elixir
- Go
- Haskell
- Haxe
- Janet
- Java
- Kotlin
- MySQL/MariaDB
- Nim
- Perl
- PHP
- Python with dictionaries
- Postgres Extension
- Postgres Native Function
- R (with dictionaries)
- Ruby
- Rust
- Swift
- Unison
- V
- Zig
此外,CLI 还可用于从命令行生成 ID。
工具
- ID size 计算器 显示调整时的碰撞概率 ID的字母或大小。
nanoid-dictionary
与常用的字母一起使用自定义字母
。nanoid-good
以确保你的ID不包含任何淫秽词汇。