مولّد 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 حرفاً:

الحجم (حرفاً)المعرّفات الممكنةأمان التصادم
664~1 من 4.5 مليار — آمن لبضعة آلاف من المعرّفات
864~1 من 4.5 تريليون — آمن لملايين المعرّفات
1164~1 من 2.8 كوادريليون — آمن لمليارات المعرّفات
1664~1 من 1.2 × 10^19 — آمن لتريليونات المعرّفات
2164~1 من 10^30 — آمن لـ 100 مليار معرّف يومياً لقرون
3264قابل للمقارنة بـ UUID v4 (122 بتاً)
3636يتجاوز UUID v4

تم اختيار الحجم الافتراضي 21 حرفاً لمطابقة مقاومة تصادم UUID v4 (~126 بتاً) مع كونه أقصر بنسبة 41%. لمعظم التطبيقات، 21 حرفاً هو الاختيار الصحيح.

الأبجديات المخصَّصة

أبجدية NanoID قابلة للتخصيص كلياً. تقبل المكتبة أي سلسلة من الأحرف الفريدة كأبجدية وتولّد المعرّفات باستخدام تلك الأحرف فقط:

أرقام فقطA-Za-z0-9_-
استخدم '0123456789' للمعرّفات المكوّنة كلها من أرقام — مفيد لرموز SMS أو معرّفات على غرار PIN.
سداسي عشري بأحرف صغيرةA-Za-z0-9
استخدم '0123456789abcdef' للسلاسل السداسية العشرية المضغوطة دون تنسيق واصلات UUID.
مقروء بشرياً0-9a-f
استبعد الأحرف الملتبسة بصرياً (0 وO و1 وI وl) للمعرّفات التي قد يحتاج المستخدمون كتابتها يدوياً.
نطاق مخصَّص0-9
استخدم أي مجموعة أحرف مناسبة لتطبيقك — مثلاً حروف علّة + حروف ساكنة فقط للمعرّفات القابلة للنطق.

مهم: استخدم nanoid/non-secure فقط للتطبيقات غير الحساسة أمنياً (مثلاً معرّفات عناصر UI). لأي معرّف يحتاج أن يكون غير قابل للتخمين، استخدم دائماً الاستيراد الافتراضي الآمن.

كيف يولّد NanoID العشوائية

يستخدم NanoID مولّد الأرقام الشبه العشوائية الآمن تشفيرياً (CSPRNG) لنظام التشغيل. في المتصفحات هذا هو crypto.getRandomValues()؛ في Node.js هو crypto.randomFillSync(). هذا مصدر الإنتروبيا ذاته المستخدَم لمفاتيح جلسات TLS — أقوى بكثير من Math.random().

أخذ العيّنات برفض (تجنّب تحيّز الباقي)

النهج الساذج لتوليد أحرف عشوائية سيكون: خذ بايتاً عشوائياً (0-255) واحسب byte % alphabetSize. هذا يُدخل تحيّز الباقي — تظهر بعض الأحرف بتكرار أعلى قليلاً من غيرها حين لا يقسم حجم الأبجدية 256 بالتساوي.

يُزيل NanoID هذا التحيّز باستخدام أخذ العيّنات برفض:

  1. حدّد أصغر قناع من قوى الاثنين يغطّي حجم الأبجدية (مثلاً لأبجدية 64 حرفاً، القناع هو 63 = 0b00111111)
  2. ولِّد بايتات عشوائية وطبّق القناع: byte & mask
  3. إذا كانت القيمة المُقنَّعة ضمن نطاق الأبجدية، استخدمها. وإلا، تجاهلها وحاول مرة أخرى.

هذا يعني أن بعض البايتات العشوائية تُرفَض، لكن الناتج توزيع منتظم تماماً على الأبجدية — لا يكون أي حرف أكثر احتمالاً من غيره.

How the algorithm works — step by step
// 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"

دعم البيئات

Browser
المتصفحات الحديثة (Chrome 37+ وFirefox 34+ وSafari 7+) — تستخدم crypto.getRandomValues()
Node.js 14+
Node.js 14.18+ — يستخدم crypto.randomFillSync()
Deno
Deno — يستخدم crypto.getRandomValues()
Bun
React Native — يستخدم expo-crypto أو polyfill من react-native-get-random-values
Edge / Cloudflare Workers
بيئات Edge (Cloudflare Workers وVercel Edge) — واجهة Web Crypto API متاحة
React Native
Bun — دعم crypto أصيلي

أمثلة الكود

JavaScript / TypeScript

JavaScript
// 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. لا حاجة لخطوة بناء للنماذج الأولية السريعة.

JavaScript
// 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

Python
# pip install nanoid
from nanoid import generate

generate()              # → "V1StGXR8_Z5jdHi6B-myT"
generate(size=8)        # → "Uakgb_J5"
generate('0123456789abcdef', 16)  # custom alphabet + size

Node.js (CommonJS)

JavaScript
// 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
}

الأسئلة الشائعة

هل NanoID آمن تشفيرياً؟
نعم — عند استخدام الاستيراد الافتراضي، يولّد NanoID معرّفات باستخدام CSPRNG على مستوى نظام التشغيل (crypto.getRandomValues في المتصفحات وcrypto.randomFillSync في Node.js). هذا مصدر الإنتروبيا ذاته المستخدَم لتوليد المفاتيح التشفيرية. قيم NanoID مناسبة لرموز الجلسة ومفاتيح API والمعرّفات الحساسة أمنياً الأخرى.
هل يمكنني استخدام NanoID كمفتاح أساسي لقاعدة بيانات؟
نعم. سلاسل NanoID آمنة في URL ويمكن تخزينها كأعمدة CHAR أو VARCHAR. غير أن NanoID ليس لديه مكوّن طابع زمني، لذا المعرّفات غير قابلة للترتيب حسب ترتيب التوليد — هذا سيسبّب تشرذم فهارس B-tree عند معدلات إدخال عالية، مشابهاً لـ UUID v4. للمفاتيح الأساسية المرتّبة زمنياً، استخدم ULID أو UUID v7.
كيف يُقارَن NanoID بـ crypto.randomUUID()؟
كلاهما يستخدم CSPRNG ويوفّر عشوائية قوية. crypto.randomUUID() أصيلي (لا تبعيات)، يولّد سلاسل UUID v4 بواصلات مكوّنة من 36 حرفاً، ومعترَف به عالمياً من قواعد البيانات والواجهات البرمجية. NanoID يتطلب حزمة npm لكنه يولّد سلاسل أقصر (21 حرفاً افتراضياً) بأبجدية قابلة للتخصيص. لمعظم الحالات، يُفضَّل crypto.randomUUID() لتجنّب التبعية.
ما الذي يحدث إذا استخدمت NanoID قصيراً جداً؟
المعرّفات القصيرة (مثلاً 6-8 أحرف) لديها احتمالية تصادم أعلى بكثير. NanoID بـ 6 أحرف من الأبجدية الافتراضية 64 حرفاً لديه فقط ~68 مليار قيمة ممكنة — مناسب لبضعة آلاف من المعرّفات قبل أن تصبح خطورة التصادم غير تافهة. استخدم جدول احتمالية التصادم أعلاه لاختيار حجم مناسب لحجم معرّفاتك المتوقَّع.
هل يمكنني استخدام NanoID في متصفح بدون npm؟
نعم. يدعم NanoID استيرادات ESM من CDN (مثلاً jsDelivr أو esm.sh). استورده كوحدة في وسم script بـ type="module". هذا مفيد للنماذج الأولية السريعة لكن غير موصَى به للإنتاج — قيّد بإصدار محدّد وفكّر في استضافة السكريبت ذاتياً.
هل يعمل NanoID في جميع البيئات؟
يعمل NanoID في جميع المتصفحات الحديثة وNode.js وDeno وBun وCloudflare Workers ووظائف Vercel Edge. لـ React Native، يلزم polyfill لـ getRandomValues (react-native-get-random-values). المكتبة مصمَّمة لتكون مستقلة عن البيئة وتكشف واجهة crypto المتاحة تلقائياً.