ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Nano ID 完整指南:118 字节的安全 URL 友好唯一 ID 生成器

Nano ID 完整指南:118 字节的安全 URL 友好唯一 ID 生成器 开发工具【免费下载链接】nanoidA tiny (118 bytes), secure, URL-friendly, unique string ID generator for JavaScript项目地址https://gitcode.com/gh_mirrors/na/nanoid点击查看免费下载导读Nano ID 是一个体积仅 118 字节minified brotli、零依赖、基于硬件随机数发生器、字符集 URL 友好的 JavaScript 唯一字符串 ID 生成器。本文以仓库根目录 README.md 为主线结合 index.js、index.browser.js、non-secure/index.js 及 test/index.test.js 等源码与测试完整讲解 Nano ID 与 UUID v4 的对比、安装方式、三类 APInanoid/customAlphabet/customRandom、安全设计、非安全变体、React / React Native / PouchDB / CLI / TypeScript 等实战用法。读完本文你将掌握如何为数据库主键、短链接、会话令牌等场景生成低碰撞概率的高性能 ID并理解其底层均匀分布算法为何比random % alphabet更安全。项目概览Nano ID 是面向 JavaScript 生态的 ID 生成库核心特性见 README.mdSmall极小压缩并 brotli 后仅 118 字节零运行时依赖包体积由 Size Limit 持续把关package.json 中为nanoid入口设定了 118 B 上限customAlphabet207 B、urlAlphabet47 B、非安全版nanoid93 B。Fast快官方基准显示其比 Node.js 原生crypto.randomUUID()快约 50%。Safe安全Node.js 环境使用crypto模块、浏览器使用 Web Crypto API 的硬件随机发生器可在集群环境使用。Short IDsID 更短采用比 UUID 更大的字符集A-Za-z0-9_-在随机位数相近的前提下ID 长度从 UUID 的 36 字符缩短到 21 字符。Portable可移植已被移植到 20 编程语言便于前后端共享同一套 ID 生成逻辑。import { nanoid } from nanoid model.id nanoid() // V1StGXR8_Z5jdHi6B-myT引文 An amazing level of senseless perfectionism, which is simply impossible not to respect.README 开篇引用了对这一工程的评价可理解为对 Nano ID 在细节上近乎偏执的工程追求的致敬无营销含义。与 UUID v4 的对比Nano ID 与随机型 UUID v4 的随机位数非常接近Nano ID 约 126 位、UUID v4 约 122 位因此碰撞概率相当。官方给出的参考数字是要出现十亿分之一one in a billion的重复概率需要生成 103 万亿个 v4 ID。该数字来自 README 原文引述用于说明在 126/122 随机位下碰撞概率极低。与 UUID v4 相比主要有两点差异见 README.md字符集更大Nano ID 使用 64 个 URL 安全字符A-Za-z0-9_-相近数量的随机位只需 21 个字符承载而 UUID 需要 36 个字符。速度更快基准显示nanoid快于crypto.randomUUID与uuid/v4。维度Nano IDUUID v4随机位数约 126 位约 122 位字符集64 个 URL 安全字符16 进制字符0-9a-fID 长度21 字符36 字符含连字符碰撞概率与 UUID v4 相当基准参照基准测试仓库自带基准脚本 test/benchmark.js在 README 中记录了基于 Node.js 的一次典型运行输出数字因硬件而异仅用于横向对比量级$ 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从中可以观察到安全版nanoid与customAlphabet在 Node 环境都稳定在 2000 万 ops/sec 量级约为原生crypto.randomUUID约 1286 万的 1.6 倍是uuid v4约 793 万的 2.5 倍以上。非安全版nanoid/non-secure反而比安全版慢这是因为其基于Math.random()的简单实现缺少安全版中的字符串池string pool优化README 中也明确提醒“非安全版本比安全版本更慢仅在必要时使用”。安全性设计Nano ID 的安全设计在 README.md 有专门论述可从三个层面理解不可预测性Unpredictability安全版不使用不安全的Math.random()Node.js 中走crypto模块浏览器中走 Web Crypto APIcrypto.getRandomValues二者均基于硬件随机发生器生成的字节不可预测。这一区别在源码层面体现为双入口设计Node 入口 index.js 用Buffer.allocUnsafecrypto.getRandomValues填充浏览器入口 index.browser.js 直接使用crypto.getRandomValues(new Uint8Array(bytes))。浏览器/React Native 场景下该替换由 package.json 中的browser与react-native字段自动完成。均匀性Uniformityrandom % alphabet.length是编写 ID 生成器时常见的错误由于 256 不一定能被字符数整除部分字符出现概率会略高导致分布不均、降低暴力破解难度。Nano ID 采用**拒绝采样rejection sampling**算法消除模偏差modulo bias并在 test/index.test.js 与 test/non-secure.test.js 中以 10 万次生成样本断言64 个字符全部出现且每个字符实际分布与理想分布的最大偏差不超过 0.05。index.js 中对应的实现要点计算safeByteCutoff 256 - (256 % alphabet.length)只接受小于该阈值的随机字节被拒绝的字节如 17 字符字母表下的 255会拉偏分布因此直接丢弃对 2 的幂长度字母表如 64 字符的urlAlphabet走 mask快速路径index.js、index.browser.js避免取模运算为保证吞吐一次请求的随机字节数按1.6的经验系数预留step Math.ceil((1.6 * 256 * defaultSize) / safeByteCutoff)用多余的字节覆盖拒绝采样带来的浪费index.js。下图直观对比了 Nano ID 与朴素random % alphabet在 26 个小写字母上的分布差异上排为nanoid生成结果的分布每个字母的条形宽度完全一致下排为random % alphabetw、x、y、z四个字母的条形明显更宽正是取模偏差的可视化体现。文档化与漏洞披露所有实现层面的技巧如safeByteCutoff的数学原理、1.6系数、字符串池优化等都以注释形式记录在 index.js 中安全漏洞请通过 Tidelift security contact 报告由 Tidelift 协调修复与披露。安装npm 安装npm install nanoid仓库 package.json 显示当前版本为6.0.1模块类型为 ESMtype: module并声明sideEffects: false以便摇树优化tree-shaking。engines字段要求 Node.js^22 || ^24 || 26使用前请确认运行环境满足该版本前提。JSR 安装JSR 是 npm 的替代包仓库开放式治理、活跃开发。对于 Node.js、Deno、Bun 等运行时npx jsr add sitnik/nanoid然后把所有导入路径中的nanoid替换为sitnik/nanoidimport { nanoid } from sitnik/nanoidDeno 用户可用deno add jsr:sitnik/nanoid安装或直接import ... from jsr:sitnik/nanoid。仓库根目录的 jsr.json 记录了 JSR 包名sitnik/nanoid与导出映射浏览器入口./index.browser.js、非安全子路径./non-secure。CDN 引入快速验证时可以从 CDN 加载README 明确不建议生产环境使用因为加载性能较低import { nanoid } from https://cdn.jsdelivr.net/npm/nanoid/nanoid.jsAPI 详解默认nanoid(size?)默认使用 URL 安全字符集A-Za-z0-9_-返回 21 字符 ID碰撞概率与 UUID v4 相当126 位随机信息import { nanoid } from nanoid model.id nanoid() // V1StGXR8_Z5jdHi6B-myT可通过size参数缩短 ID同时意味着碰撞概率上升nanoid(10) // IRFa-VaY2b缩短 ID 前建议用 ID 碰撞概率计算器评估安全性。实现上nanoid即customAlphabet(urlAlphabet)的实例index.js、index.browser.js默认size为 21index.d.ts。自定义字符集与长度customAlphabet(alphabet, defaultSize 21)customAlphabet返回一个可生成指定字符集与默认长度的nanoid函数import { customAlphabet } from nanoid const nanoid customAlphabet(1234567890abcdef, 10) model.id nanoid() // 4f90d13a42非安全版同样提供customAlphabet导入路径nanoid/non-secure。字符集长度约束字母表必须不超过 256 个符号否则内部生成算法的安全性无法保证README 明确说明index.d.ts 同步声明。这是出于safeByteCutoff拒绝采样算法的前提——字节取值 0-255字母表超过 256 时无法建立均匀映射。运行时覆盖长度除了构造函数中设置默认长度调用时还可以临时指定import { customAlphabet } from nanoid const nanoid customAlphabet(1234567890abcdef, 10) model.id nanoid(5) // f01a2源码级优化index.jsNode 版对纯 ASCII 单字节字符集走“字符串池”快速路径——把字符码写入Uint8Array随机填充后一次性Buffer#toString(latin1)每个 ID 用substring截取避免逐字符拼接池大小从首次请求尺寸开始、以 16 倍几何增长上限为GET_RANDOM_LIMIT / 2即 32768 字节短生命周期调用不会付出整池成本。对于多字节如中文、西里尔字母或超过 256 符号的字母表则自动回退到customRandom通用路径index.js测试 test/index.test.js 覆盖了多字节字符与非字符串数组字母表场景。自定义随机字节源customRandom(alphabet, defaultSize, random)customRandom允许同时替换字母表与随机字节生成器。例如使用基于种子的生成器便于复现测试import { customRandom } from nanoid const rng seedrandom(seed) const nanoid customRandom(abcdef, 10, size { return new Uint8Array(size).map(() 256 * rng()) }) nanoid() // fbaefaadebrandom回调必须接受数组大小字节数并返回同样长度的随机数字数组如Uint8Array见 index.d.ts 的类型签名。如果希望保留默认 URL 安全字符集、只替换随机源可导入urlAlphabetimport { customRandom, urlAlphabet } from nanoid const nanoid customRandom(urlAlphabet, 10, random)urlAlphabet的定义在 url-alphabet/index.js共 64 个字符useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict字符顺序针对 gzip/brotli 压缩优化注释中列明了与压缩字典的引用关系。测试 test/index.test.js 验证其长度为 64、无重复字符。注意事项不同 Nano ID 版本之间可能调整随机生成器的调用序列因此若使用种子型生成器不能保证跨版本得到相同结果。非安全版本nanoid/non-secure安全版依赖硬件随机字节生成碰撞概率低如果对安全性要求不高或运行环境没有硬件随机发生器可以使用非安全版本import { nanoid } from nanoid/non-secure const id nanoid() // Uakgb_J5m9g-0JDMbcJqLJ非安全版实现见 non-secure/index.js基于Math.random()用(Math.random() * alphabet.length) | 0取索引| 0比Math.floor()更紧凑、更快并通过i | 0防止负长度导致死循环。请牢记 README 的警告非安全版比安全版更慢缺乏字符串池优化仅在必须使用时才选用。实战用法ReactREADME 明确指出React 的keyprop 没有使用 Nano ID 的正确姿势因为key需要在多次渲染间保持一致而nanoid()每次调用都会产生新值。function Todos({ todos }) { return ( ul {todos.map(todo ( li key{nanoid()} { } /* DON’T DO IT */ {todo.text} /li ))} /ul ) }正确的做法是优先使用列表项自带的稳定 IDconst todoItems todos.map(todo li key{todo.id}{todo.text}/li)若列表项没有稳定 ID退而求其次使用索引仍不推荐但优于nanoid()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 ))如果只是需要把 label 与 input 关联起来的随机 IDReact 18 引入的useId是更合适的选择。React NativeReact Native 没有内置随机发生器需要先安装react-native-get-random-valuespolyfill适用于原生 React Native 及 Expo 39.x 及以上并在导入 Nano ID 之前导入它import react-native-get-random-values import { nanoid } from nanoidpackage.json 的react-native字段会把index.js映射到index.browser.js即走crypto.getRandomValues路径。PouchDB 与 CouchDBPouchDB/CouchDB 的文档 ID 不能以下划线_开头而 Nano ID 默认字符集包含_ID 可能恰好以_开头。因此需要加前缀db.put({ _id: id nanoid(), … })CLI 命令行使用无需在系统中安装 Nano ID只要装了 Node.js就可以用npx nanoid在终端生成 ID$ npx nanoid npx: installed 1 in 0.63s LZfXLFzPPR4NNrgjlWDxn用--size或-s指定长度$ npx nanoid --size 10 L3til0JS4z用--alphabet或-a指定自定义字符集——注意此时必须同时提供--size$ npx nanoid --alphabet abc --size 15 bccbcabaabaccabCLI 实现见 bin/nanoid.js由 package.json 的bin字段声明支持-v/--version与-h/--help帮助文本内含用法示例--size解析为数字若为NaN或非正数会报错 Size must be positive integer未知参数直接报错退出。自定义字符集时底层调用customAlphabet(alphabet, size)否则调用nanoid(size)。TypeScript 泛型支持Nano ID 允许把生成结果转换为不透明字符串类型opaque string。例如定义品牌化类型UserIddeclare const userIdBrand: unique symbol type UserId string { [userIdBrand]: true } // Use explicit type parameter: mockUser(nanoidUserId()) interface User { id: UserId name: string } const user: User { // Automatically casts to UserId: id: nanoid(), name: Alice }类型签名见 index.d.ts、index.d.tsnanoidType extends string()与customAlphabet均支持泛型参数non-secure/index.d.ts 中非安全版同样提供泛型支持。其他编程语言移植Nano ID 已被移植到 20 语言/平台可让客户端与服务端使用同一套 ID 生成逻辑包括C、C#、C、Clojure/ClojureScript、ColdFusion/CFML、Crystal、Dart Flutter、Elixir、Gleam、Go、Haskell、Haxe、Janet、Java、Kotlin、MySQL/MariaDB、Nim、OCaml、Perl、PHP、Python原生实现及 Rust 加速版、PostgresExtension 与 Native Function、R、Ruby、Rust、Swift、Unison、V、Zig。对于尚未移植的环境可直接使用上面介绍的 CLI 生成 ID。配套工具ID 碰撞概率计算器调整字符集或 ID 长度时评估碰撞概率的安全工具。nanoid-dictionary提供常用字符集字典配合customAlphabet使用。nanoid-good用于确保生成的 ID 不含任何粗俗词汇。从源码看运行前提与限制运行环境安全版要求运行环境提供crypto.getRandomValuesNode 22/24/26 或浏览器 Web Crypto非安全版只需Math.random()。长度上限crypto.getRandomValues单次拒绝超过 65536 字节的请求index.js 通过fillRandom分块填充更大的缓冲区因此支持生成 70000 字符级别的超长 ID对应测试 test/index.test.js。输入防御size | 0把参数强制转为数字防止valueOf滥用污染字符串池偏移index.js相关回归测试见 test/index.test.js 与 test/index.test.js。非法参数负数或超大的 ID 长度会抛出RangeError(Wrong ID size)index.js或底层 TypedArray 异常nanoid(0)返回空字符串index.js。测试体系仓库通过 test/index.test.jsNode 与浏览器双入口、覆盖分布均匀性/无碰撞/超长 ID/customRandom 确定性序列等、test/non-secure.test.js 与 test/benchmark.js 保障实现质量pnpm test会串起 lint、size-limit、版本检查与预构建检查等脚本见 package.json。结语Nano ID 以 118 字节的极致体积在字符集、随机位、速度与安全性之间取得了精巧的平衡更大的 64 字符 URL 安全字符集让 21 字符 ID 承载约 126 位随机信息硬件随机源与拒绝采样算法保证了不可预测性与均匀分布字符串池等微观优化带来了远超crypto.randomUUID的吞吐。本文涉及的源码路径均可继续深入研读例如 index.js核心算法与优化注释、index.browser.js浏览器入口、non-secure/index.js非安全变体、url-alphabet/index.js默认字符集以及 test/index.test.js行为契约。在你选择自己的 ID 策略时请记住 README 的忠告缩短长度前用碰撞概率计算器评估安全边界非安全版仅在环境限制下使用。赞分享开发工具【免费下载链接】nanoidA tiny (118 bytes), secure, URL-friendly, unique string ID generator for JavaScript项目地址https://gitcode.com/gh_mirrors/na/nanoid点击查看免费下载相关推荐CKEditor 5 集成 Spring Boot基于 ZIP 自托管部署完整指南CKEditor 5 集成 Spring Boot基于 ZIP 自托管部署完整指南 导读 本文基于 CKEditor 5 官方文档《Integrating C开发工具free-stockdb分钟数据跨日查询技巧8位日期如何自动补全为14位时间戳free stockdb分钟数据跨日查询技巧8位日期如何自动补全为14位时间戳 free stockdb 是一款面向 A 股日K、分钟K与ETF分钟数据的本地开发工具NanoID: 简洁而安全的URL友好唯一字符串ID生成器NanoID: 简洁而安全的URL友好唯一字符串ID生成器 一、项目介绍 NanoID 是一款轻量级 大小仅124字节 、安全且友好的唯一字符串ID生成库专为开发工具上一篇GitHub Linguist错误恢复机制处理损坏文件的策略下一篇AtlasOS 10 分钟上手让 Windows 11 变轻变快的实用调优教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表