这些库用于在 JavaScript 环境中生成唯一字符串。nanoid 是现代首选,兼顾安全与体积。uuid 提供标准 RFC 格式,适合系统间互通。shortid 已废弃,存在安全风险。randomstring 适合生成临时令牌,但安全性需自行确认。
在前端开发中,生成唯一标识符(ID)是常见需求,无论是用于列表渲染的 key、临时会话令牌,还是资源追踪。nanoid、uuid、shortid 和 randomstring 都是流行的选择,但它们在安全性、格式标准和维护状态上有显著差异。让我们从架构师的角度深入比较这些方案。
生成 ID 的核心在于随机性。如果随机性不足,ID 可能被预测,导致安全漏洞。
nanoid 默认使用加密安全的随机生成器。
crypto 模块。getRandomValues。// nanoid: 默认安全
import { nanoid } from 'nanoid';
const id = nanoid(); // 默认 21 字符,安全随机
uuid (v4) 也使用加密安全的随机数。
// uuid: v4 安全
import { v4 as uuidv4 } from 'uuid';
const id = uuidv4(); // 标准 UUID 格式
shortid 存在已知安全问题。
// shortid: 不推荐
import shortid from 'shortid';
const id = shortid.generate(); // 存在安全风险
randomstring 安全性取决于环境。
crypto。Math.random(不安全)。// randomstring: 需确认环境
import randomstring from 'randomstring';
const id = randomstring.generate(); // 默认可能不安全
不同的业务场景对 ID 的长度和字符集有不同要求。
nanoid 生成 URL 友好的字符串。
_ 和 -。// nanoid: 自定义长度
import { nanoid } from 'nanoid';
const id = nanoid(10); // 10 字符
uuid 格式固定且较长。
// uuid: 固定格式
import { v4 as uuidv4 } from 'uuid';
const id = uuidv4(); // 36 字符,如 550e8400-e29b...
shortid 生成短字符串。
// shortid: 短但不固定
import shortid from 'shortid';
const id = shortid.generate(); // 长度可变
randomstring 提供高度自定义。
// randomstring: 自定义字符集
import randomstring from 'randomstring';
const id = randomstring.generate({ length: 10, charset: 'numeric' });
前端项目对 bundle 大小敏感,库的体积直接影响加载性能。
nanoid 体积极小。
// nanoid: 轻量导入
import { nanoid } from 'nanoid';
uuid 体积相对较大。
nanoid 大。// uuid: 按需导入
import { v4 as uuidv4 } from 'uuid';
shortid 体积中等。
// shortid: 旧式导入
import shortid from 'shortid';
randomstring 体积较小。
// randomstring: 简单导入
import randomstring from 'randomstring';
选择库时,维护状态决定了未来的技术债务。
nanoid 活跃维护。
shortid 的替代品。uuid 稳定维护。
shortid 已废弃。
randomstring 维护较少。
| 特性 | nanoid | uuid | shortid | randomstring |
|---|---|---|---|---|
| 安全性 | ✅ 加密安全 | ✅ 加密安全 (v4) | ❌ 存在风险 | ⚠️ 依赖环境 |
| 格式 | URL 友好 | RFC 4122 标准 | 短字符串 | 高度自定义 |
| 体积 | 极小 | 中等 | 中等 | 小 |
| 维护状态 | ✅ 活跃 | ✅ 稳定 | ❌ 已废弃 | ⚠️ 较少更新 |
| 推荐场景 | 默认首选 | 系统互通 | 无 (已废弃) | 临时令牌/密码 |
nanoid 是现代前端开发的默认选择 — 它安全、小巧且易于使用。除非你有特殊需求,否则应优先使用它。
uuid 仅在需要与后端系统严格匹配标准格式时使用。它的通用性值得额外的体积开销。
shortid 必须避免 — 它已废弃且不安全。迁移到 nanoid 只需几分钟,但能消除长期风险。
randomstring 适合特定场景 — 如生成仅数字的验证码。但在生成用户 ID 或会话令牌时,请谨慎评估其安全性。
核心原则:ID 生成看似简单,却关乎应用安全。选择经过验证、 actively maintained 的库 — 不要为了微小的便利牺牲安全性。
当后端系统或数据库强制要求 RFC 4122 标准格式时使用。虽然体积较大,但通用性最强,适合分布式系统追踪或需要标准格式的场景。
如果你的项目需要安全、简短且 URL 友好的 ID,这是默认选择。它在浏览器和 Node.js 中都能保持 cryptographically secure,且体积极小。适合大多数前端场景,如列表键值或临时资源 ID。
适用于生成非安全敏感的临时令牌或密码,且需要高度自定义字符集时。如果不需要标准格式且 nanoid 的字符集不满足需求,可以考虑它,但需注意浏览器端的安全性。
不要在的新项目中使用此包。它已正式废弃且存在已知安全漏洞,作者明确建议迁移至 nanoid。继续使用会带来维护风险和潜在的安全隐患。
For the creation of RFC9562 (formerly RFC4122) UUIDs
crypto API for random valuesuuid command line utility[!NOTE]
Starting with
uuid@12CommonJS is no longer supported. See implications and motivation for details.
1. Install
npm install uuid
2. Create a UUID
import { v4 as uuidv4 } from 'uuid';
uuidv4(); // ⇨ 'b18794e8-5d0d-417c-b361-ba38e78411b4'
For timestamp UUIDs, namespace UUIDs, and other options read on ...
uuid.NIL | The nil UUID string (all zeros) |
uuid.MAX | The max UUID string (all ones) |
uuid.parse() | Convert UUID string to array of bytes |
uuid.stringify() | Convert array of bytes to UUID string |
uuid.v1() | Generate a version 1 (timestamp) UUID |
uuid.v1ToV6() | Convert a version 1 UUID to version 6 |
uuid.v3() | Generate a version 3 (namespace w/ MD5) UUID |
uuid.v4() | Generate a version 4 (random) UUID |
uuid.v5() | Generate a version 5 (namespace w/ SHA-1) UUID |
uuid.v6() | Generate a version 6 (timestamp, reordered) UUID |
uuid.v6ToV1() | Convert a version 6 UUID to version 1 |
uuid.v7() | Generate a version 7 (Unix Epoch time-based) UUID |
uuid.v8() | "Intentionally left blank" |
uuid.validate() | Test a string to see if it is a valid UUID |
uuid.version() | Detect RFC version of a UUID |
The nil UUID string (all zeros).
Example:
import { NIL as NIL_UUID } from 'uuid';
NIL_UUID; // ⇨ '00000000-0000-0000-0000-000000000000'
The max UUID string (all ones).
Example:
import { MAX as MAX_UUID } from 'uuid';
MAX_UUID; // ⇨ 'ffffffff-ffff-ffff-ffff-ffffffffffff'
Convert UUID string to array of bytes
str | A valid UUID String |
| returns | Uint8Array[16] |
| throws | TypeError if str is not a valid UUID |
[!NOTE] Ordering of values in the byte arrays used by
parse()andstringify()follows the left ↠ right order of hex-pairs in UUID strings. As shown in the example below.
Example:
import { parse as uuidParse } from 'uuid';
// Parse a UUID
uuidParse('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨
// Uint8Array(16) [
// 110, 192, 189, 127, 17,
// 192, 67, 218, 151, 94,
// 42, 138, 217, 235, 174,
// 11
// ]
Convert array of bytes to UUID string
arr | Array-like collection of 16 values (starting from offset) between 0-255. |
[offset = 0] | Number Starting index in the Array |
| returns | String |
| throws | TypeError if a valid UUID string cannot be generated |
[!NOTE] Ordering of values in the byte arrays used by
parse()andstringify()follows the left ↠ right order of hex-pairs in UUID strings. As shown in the example below.
Example:
import { stringify as uuidStringify } from 'uuid';
const uuidBytes = Uint8Array.of(
0x6e,
0xc0,
0xbd,
0x7f,
0x11,
0xc0,
0x43,
0xda,
0x97,
0x5e,
0x2a,
0x8a,
0xd9,
0xeb,
0xae,
0x0b
);
uuidStringify(uuidBytes); // ⇨ '6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'
Create an RFC version 1 (timestamp) UUID
[options] | Object with one or more of the following properties: |
[options.node = (random) ] | RFC "node" field as an Array[6] of byte values (per 4.1.6) |
[options.clockseq = (random)] | RFC "clock sequence" as a Number between 0 - 0x3fff |
[options.msecs = (current time)] | RFC "timestamp" field (Number of milliseconds, unix epoch) |
[options.nsecs = 0] | RFC "timestamp" field (Number of nanoseconds to add to msecs, should be 0-10,000) |
[options.random = (random)] | Array of 16 random bytes (0-255) used to generate other fields, above |
[options.rng] | Alternative to options.random, a Function that returns an Array of 16 random bytes (0-255) |
[buffer] | Uint8Array or Uint8Array subtype (e.g. Node.js Buffer). If provided, binary UUID is written into the array, starting at offset |
[offset = 0] | Number Index to start writing UUID bytes in buffer |
| returns | UUID String if no buffer is specified, otherwise returns buffer |
| throws | Error if more than 10M UUIDs/sec are requested |
Example:
import { v1 as uuidv1 } from 'uuid';
uuidv1(); // ⇨ '57fd0000-c7d3-11ef-841d-514d2167fc5b'
Example using options:
import { v1 as uuidv1 } from 'uuid';
const options = {
node: Uint8Array.of(0x01, 0x23, 0x45, 0x67, 0x89, 0xab),
clockseq: 0x1234,
msecs: new Date('2011-11-01').getTime(),
nsecs: 5678,
};
uuidv1(options); // ⇨ '710b962e-041c-11e1-9234-0123456789ab'
Convert a UUID from version 1 to version 6
import { v1ToV6 } from 'uuid';
v1ToV6('92f62d9e-22c4-11ef-97e9-325096b39f47'); // ⇨ '1ef22c49-2f62-6d9e-97e9-325096b39f47'
Create an RFC version 3 (namespace w/ MD5) UUID
API is identical to v5(), but uses "v3" instead.
[!IMPORTANT] Per the RFC, "If backward compatibility is not an issue, SHA-1 [Version 5] is preferred."
Create an RFC version 4 (random) UUID
[options] | Object with one or more of the following properties: |
[options.random] | Array of 16 random bytes (0-255) |
[options.rng] | Alternative to options.random, a Function that returns an Array of 16 random bytes (0-255) |
[buffer] | Uint8Array or Uint8Array subtype (e.g. Node.js Buffer). If provided, binary UUID is written into the array, starting at offset |
[offset = 0] | Number Index to start writing UUID bytes in buffer |
| returns | UUID String if no buffer is specified, otherwise returns buffer |
Example:
import { v4 as uuidv4 } from 'uuid';
uuidv4(); // ⇨ 'b18794e8-5d0d-417c-b361-ba38e78411b4'
Example using predefined random values:
import { v4 as uuidv4 } from 'uuid';
const v4options = {
random: Uint8Array.of(
0x10,
0x91,
0x56,
0xbe,
0xc4,
0xfb,
0xc1,
0xea,
0x71,
0xb4,
0xef,
0xe1,
0x67,
0x1c,
0x58,
0x36
),
};
uuidv4(v4options); // ⇨ '109156be-c4fb-41ea-b1b4-efe1671c5836'
Create an RFC version 5 (namespace w/ SHA-1) UUID
name | String | Array |
namespace | String | Array[16] Namespace UUID |
[buffer] | Uint8Array or Uint8Array subtype (e.g. Node.js Buffer). If provided, binary UUID is written into the array, starting at offset |
[offset = 0] | Number Index to start writing UUID bytes in buffer |
| returns | UUID String if no buffer is specified, otherwise returns buffer |
[!NOTE] The RFC
DNSandURLnamespaces are available asv5.DNSandv5.URL.
Example with custom namespace:
import { v5 as uuidv5 } from 'uuid';
// Define a custom namespace. Readers, create your own using something like
// https://www.uuidgenerator.net/
const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';
uuidv5('Hello, World!', MY_NAMESPACE); // ⇨ '630eb68f-e0fa-5ecc-887a-7c7a62614681'
Example with RFC URL namespace:
import { v5 as uuidv5 } from 'uuid';
uuidv5('https://www.w3.org/', uuidv5.URL); // ⇨ 'c106a26a-21bb-5538-8bf2-57095d1976c1'
Create an RFC version 6 (timestamp, reordered) UUID
This method takes the same arguments as uuid.v1().
import { v6 as uuidv6 } from 'uuid';
uuidv6(); // ⇨ '1efc7d35-7fd0-6000-841d-504d2167fc5b'
Example using options:
import { v6 as uuidv6 } from 'uuid';
const options = {
node: [0x01, 0x23, 0x45, 0x67, 0x89, 0xab],
clockseq: 0x1234,
msecs: new Date('2011-11-01').getTime(),
nsecs: 5678,
};
uuidv6(options); // ⇨ '1e1041c7-10b9-662e-9234-0123456789ab'
Convert a UUID from version 6 to version 1
import { v6ToV1 } from 'uuid';
v6ToV1('1ef22c49-2f62-6d9e-97e9-325096b39f47'); // ⇨ '92f62d9e-22c4-11ef-97e9-325096b39f47'
Create an RFC version 7 (random) UUID
[options] | Object with one or more of the following properties: |
[options.msecs = (current time)] | RFC "timestamp" field (Number of milliseconds, unix epoch) |
[options.random = (random)] | Array of 16 random bytes (0-255) used to generate other fields, above |
[options.rng] | Alternative to options.random, a Function that returns an Array of 16 random bytes (0-255) |
[options.seq = (random)] | 32-bit sequence Number between 0 - 0xffffffff. This may be provided to help ensure uniqueness for UUIDs generated within the same millisecond time interval. Default = random value. |
[buffer] | Uint8Array or Uint8Array subtype (e.g. Node.js Buffer). If provided, binary UUID is written into the array, starting at offset |
[offset = 0] | Number Index to start writing UUID bytes in buffer |
| returns | UUID String if no buffer is specified, otherwise returns buffer |
Example:
import { v7 as uuidv7 } from 'uuid';
uuidv7(); // ⇨ '01941f29-7c00-73e4-a310-744d2167fc5b'
"Intentionally left blank"
[!NOTE] Version 8 (experimental) UUIDs are "for experimental or vendor-specific use cases". The RFC does not define a creation algorithm for them, which is why this package does not offer a
v8()method. Thevalidate()andversion()methods do work with such UUIDs, however.
Test a string to see if it is a valid UUID
str | String to validate |
| returns | true if string is a valid UUID, false otherwise |
Example:
import { validate as uuidValidate } from 'uuid';
uuidValidate('not a UUID'); // ⇨ false
uuidValidate('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨ true
Using validate and version together it is possible to do per-version validation, e.g. validate for only v4 UUIds.
import { version as uuidVersion } from 'uuid';
import { validate as uuidValidate } from 'uuid';
function uuidValidateV4(uuid) {
return uuidValidate(uuid) && uuidVersion(uuid) === 4;
}
const v1Uuid = 'd9428888-122b-11e1-b85c-61cd3cbb3210';
const v4Uuid = '109156be-c4fb-41ea-b1b4-efe1671c5836';
uuidValidateV4(v4Uuid); // ⇨ true
uuidValidateV4(v1Uuid); // ⇨ false
Detect RFC version of a UUID
str | A valid UUID String |
| returns | Number The RFC version of the UUID |
| throws | TypeError if str is not a valid UUID |
Example:
import { version as uuidVersion } from 'uuid';
uuidVersion('45637ec4-c85f-11ea-87d0-0242ac130003'); // ⇨ 1
uuidVersion('6ec0bd7f-11c0-43da-975e-2a8ad9ebae0b'); // ⇨ 4
[!NOTE] This method returns
0for theNILUUID, and15for theMAXUUID.
UUIDs can be generated from the command line using uuid.
$ npx uuid
ddeb27fb-d9a0-4624-be4d-4615062daed4
The default is to generate version 4 UUIDS, however the other versions are supported. Type uuid --help for details:
$ npx uuid --help
Usage:
uuid
uuid v1
uuid v3 <name> <namespace uuid>
uuid v4
uuid v5 <name> <namespace uuid>
uuid v7
uuid --help
Note: <namespace uuid> may be "URL" or "DNS" to use the corresponding UUIDs
defined by RFC9562
options Handling for Timestamp UUIDsPrior to uuid@11, it was possible for options state to interfere with the internal state used to ensure uniqueness of timestamp-based UUIDs (the v1(), v6(), and v7() methods). Starting with uuid@11, this issue has been addressed by using the presence of the options argument as a flag to select between two possible behaviors:
options: Internal state is utilized to improve UUID uniqueness.options: Internal state is NOT used and, instead, appropriate defaults are applied as needed.Browsers: uuid builds are tested against the latest version of desktop Chrome, Safari, Firefox, and Edge. Mobile versions of these same browsers are expected to work but aren't currently tested.
Node: uuid builds are tested against node (LTS releases), plus one prior. E.g. At the time of this writing node@20 is the "maintenance" release and node@24 is the "current" release, so uuid supports node@20-node@24.
Typescript: TS versions released within the past two years are supported. source
This error occurs in environments where the standard crypto.getRandomValues() API is not supported. This issue can be resolved by adding an appropriate polyfill:
react-native-get-random-valuesuuid. Since uuid might also appear as a transitive dependency of some other imports it's safest to just import react-native-get-random-values as the very first thing in your entry point:import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';
Generated from README_js.md by runmd