مولّد NanoID
يولد معرفات فريدة صغيرة وآمنة للرابط مع أبجدية قابلة للتخصيص
الأبجدية
الحجم
العدد
انقر على توليد لإنشاء NanoIDs
ما هو NanoID؟
NanoID مولّد معرّفات عشوائي صغير وسريع وآمن في عناوين URL. يولّد افتراضياً سلاسل مكوّنة من 21 حرفاً باستخدام أبجدية 64 حرفاً (A-Za-z0-9_-)، موفّراً تقريباً 126 بت من الإنتروبيا — قابلاً للمقارنة بـ 122 بت في UUID v4 لكن في سلسلة أقصر.
لا يضمّ NanoID طابعاً زمنياً أو أي بيانات منظَّمة. كل معرّف عشوائي بالكامل، مولَّد من مولّد الأرقام العشوائية الآمن تشفيرياً في نظام التشغيل (crypto.getRandomValues() في المتصفحات، crypto.randomBytes() في Node.js).
NanoID مقابل UUID v4
NanoID وUUID v4 كلاهما مولّدا معرّفات عشوائية مدعومان بـ CSPRNG. يختلفان في التنسيق والطول ودعم النظام البيئي:
| الخاصية | NanoID (افتراضي) | UUID v4 |
|---|---|---|
| التنسيق | حروفي رقمي آمن في URL + _- | سداسي عشري بواصلات |
| الطول | 21 حرفاً (افتراضي) | 36 حرفاً |
| الإنتروبيا | ~126 بتاً | 122 بتاً |
| آمن في URL | نعم — لا حاجة لترميز | نعم (مع واصلات) |
| الأبجدية | 64 حرفاً (A-Za-z0-9_-) | 16 حرفاً (0-9a-f) |
| التبعيات | يتطلب حزمة npm | أصيلي (crypto.randomUUID) |
| قابل للتخصيص | نعم — الطول والأبجدية | لا |
| المعيار | لا شيء (مكتبة مجتمعية) | RFC 4122 / RFC 9562 |
اختر UUID v4 حين تهمّ قابلية التشغيل البيني مع أنظمة خارجية — قواعد البيانات ذات أعمدة UUID أصيلية وواجهات برمجية تتوقع تنسيق UUID أو بنية تحتية للتسجيل تحلّل UUID. اختر NanoID حين تريد معرّفات أقصر وتتحكّم في المكدّس الكامل.
احتمالية التصادم حسب الحجم
تعتمد احتمالية التصادم في NanoID على طول المعرّف ومعدّل التوليد. يستخدم الجدول التالي الأبجدية الافتراضية المكوّنة من 64 حرفاً:
| الحجم (حرفاً) | المعرّفات الممكنة | أمان التصادم |
|---|---|---|
| 6 | 64 | ~1 من 4.5 مليار — آمن لبضعة آلاف من المعرّفات |
| 8 | 64 | ~1 من 4.5 تريليون — آمن لملايين المعرّفات |
| 11 | 64 | ~1 من 2.8 كوادريليون — آمن لمليارات المعرّفات |
| 16 | 64 | ~1 من 1.2 × 10^19 — آمن لتريليونات المعرّفات |
| 21 | 64 | ~1 من 10^30 — آمن لـ 100 مليار معرّف يومياً لقرون |
| 32 | 64 | قابل للمقارنة بـ UUID v4 (122 بتاً) |
| 36 | 36 | يتجاوز UUID v4 |
تم اختيار الحجم الافتراضي 21 حرفاً لمطابقة مقاومة تصادم UUID v4 (~126 بتاً) مع كونه أقصر بنسبة 41%. لمعظم التطبيقات، 21 حرفاً هو الاختيار الصحيح.
الأبجديات المخصَّصة
أبجدية NanoID قابلة للتخصيص كلياً. تقبل المكتبة أي سلسلة من الأحرف الفريدة كأبجدية وتولّد المعرّفات باستخدام تلك الأحرف فقط:
A-Za-z0-9_-A-Za-z0-90-9a-f0-9مهم: استخدم nanoid/non-secure فقط للتطبيقات غير الحساسة أمنياً (مثلاً معرّفات عناصر UI). لأي معرّف يحتاج أن يكون غير قابل للتخمين، استخدم دائماً الاستيراد الافتراضي الآمن.
كيف يولّد NanoID العشوائية
يستخدم NanoID مولّد الأرقام الشبه العشوائية الآمن تشفيرياً (CSPRNG) لنظام التشغيل. في المتصفحات هذا هو crypto.getRandomValues()؛ في Node.js هو crypto.randomFillSync(). هذا مصدر الإنتروبيا ذاته المستخدَم لمفاتيح جلسات TLS — أقوى بكثير من Math.random().
أخذ العيّنات برفض (تجنّب تحيّز الباقي)
النهج الساذج لتوليد أحرف عشوائية سيكون: خذ بايتاً عشوائياً (0-255) واحسب byte % alphabetSize. هذا يُدخل تحيّز الباقي — تظهر بعض الأحرف بتكرار أعلى قليلاً من غيرها حين لا يقسم حجم الأبجدية 256 بالتساوي.
يُزيل NanoID هذا التحيّز باستخدام أخذ العيّنات برفض:
- حدّد أصغر قناع من قوى الاثنين يغطّي حجم الأبجدية (مثلاً لأبجدية 64 حرفاً، القناع هو 63 = 0b00111111)
- ولِّد بايتات عشوائية وطبّق القناع:
byte & mask - إذا كانت القيمة المُقنَّعة ضمن نطاق الأبجدية، استخدمها. وإلا، تجاهلها وحاول مرة أخرى.
هذا يعني أن بعض البايتات العشوائية تُرفَض، لكن الناتج توزيع منتظم تماماً على الأبجدية — لا يكون أي حرف أكثر احتمالاً من غيره.
// Pure browser — no npm package needed
function generateNanoid(alphabet, size) {
const mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
const step = Math.ceil((1.6 * mask * size) / alphabet.length)
let id = ''
while (id.length < size) {
const bytes = crypto.getRandomValues(new Uint8Array(step))
for (const byte of bytes) {
const idx = byte & mask
if (idx < alphabet.length) {
id += alphabet[idx]
if (id.length === size) break
}
}
}
return id
}
const URL_SAFE = 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
generateNanoid(URL_SAFE, 21) // → "V1StGXR8_Z5jdHi6B-myT"دعم البيئات
أمثلة الكود
JavaScript / TypeScript
// npm i nanoid
import { nanoid } from 'nanoid'
nanoid() // → "V1StGXR8_Z5jdHi6B-myT" (21 chars, URL-safe)
nanoid(8) // → "Uakgb_J5" (custom size)
// Custom alphabet
import { customAlphabet } from 'nanoid'
const hexId = customAlphabet('0123456789abcdef', 16)
hexId() // → "4f3a1b8c9d2e0f7a"
const numId = customAlphabet('0123456789', 8)
numId() // → "30812894"المتصفح (CDN)
يمكن استخدام NanoID مباشرةً في المتصفح عبر استيراد CDN. لا حاجة لخطوة بناء للنماذج الأولية السريعة.
// Pure browser — no npm package needed
function generateNanoid(alphabet, size) {
const mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
const step = Math.ceil((1.6 * mask * size) / alphabet.length)
let id = ''
while (id.length < size) {
const bytes = crypto.getRandomValues(new Uint8Array(step))
for (const byte of bytes) {
const idx = byte & mask
if (idx < alphabet.length) {
id += alphabet[idx]
if (id.length === size) break
}
}
}
return id
}
const URL_SAFE = 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
generateNanoid(URL_SAFE, 21) // → "V1StGXR8_Z5jdHi6B-myT"Python
# pip install nanoid
from nanoid import generate
generate() # → "V1StGXR8_Z5jdHi6B-myT"
generate(size=8) # → "Uakgb_J5"
generate('0123456789abcdef', 16) # custom alphabet + sizeNode.js (CommonJS)
// Node.js — stdlib only, no npm needed
const { randomFillSync } = require('crypto')
function nanoid(alphabet, size) {
const mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
const step = Math.ceil((1.6 * mask * size) / alphabet.length)
let id = ''
while (id.length < size) {
const bytes = randomFillSync(Buffer.alloc(step))
for (const byte of bytes) {
const idx = byte & mask
if (idx < alphabet.length) { id += alphabet[idx]; if (id.length === size) break }
}
}
return id
}