はじめに
「データベースの主キーやReactのkey属性に使うユニークなID、どうやって生成していますか?」
多くの方が真っ先に思い浮かべるのはUUIDでしょう。しかし、110ec58a-a0f2-4ac4-8393-c866d813b8d1 のような36文字のIDは、URLに含めると長くて不格好ですし、ハイフンが視認性を下げます。かといって Math.random() で自作すると、衝突(重複)のリスクや予測可能性というセキュリティ上の問題を抱えることになります。
そんな悩みを一気に解決してくれるのが「Nano ID」です。わずか118バイト(minified + brotli圧縮時)という驚異的な軽さで、UUIDと同等の安全性を持つ21文字のURLフレンドリーなIDを生成できます。この記事では、Nano IDの基本から実践的な使い方まで、コピペで動くコード例とともに解説します。
Nano IDとは
Nano IDは、JavaScript向けの小さくて安全なユニークID生成ライブラリです。ロシアのAndrey Sitnik氏(PostCSSやAutoprefixerの作者としても有名です)によって開発され、GitHubで25k以上のスターを獲得しています。
npmでのダウンロード数は週間数千万回にのぼり、事実上の標準ID生成ライブラリとして幅広いプロジェクトで採用されています。MITライセンスのオープンソースで、2026年7月にはv6系がリリースされるなど、現在も活発に開発が続いています。
主な特徴
- 超軽量 - minified + brotli圧縮でわずか118バイト。依存パッケージはゼロなので、バンドルサイズをほとんど増やしません
- 高速かつ安全 - ハードウェア乱数生成器(Web Crypto API)を使用し、暗号学的に強度のあるIDを生成します。それでいてネイティブの
crypto.randomUUID()より高速です - 短くてURLフレンドリー - デフォルトのアルファベットは
A-Za-z0-9_-の64文字。UUIDの36文字に対して21文字と短く、そのままURLに埋め込めます - 衝突確率はUUIDv4と同等 - 記号を増やしてIDを短くしただけで、乱数の情報量は確保されています。10億分の1の確率で重複が起きるには、103兆個のIDを生成する必要があります
- 多言語対応 - 本家のJavaScript版以外にも、Python、Go、Rust、Javaなど20以上の言語に移植されています
インストール
npmやyarn、pnpmでインストールできます。
# npm
npm install nanoid
# yarn
yarn add nanoid
# pnpm
pnpm add nanoid
DenoやBunではJSR経由でもインストールできます。
npx jsr add @sitnik/nanoid
ビルドツールを使わない場合は、CDNから直接インポートすることも可能です。
import { nanoid } from 'https://cdn.jsdelivr.net/npm/nanoid/nanoid.js'
なお、Nano IDはESMパッケージですが、Node.js 22.12以降であればCommonJSの require() からも読み込めます。
基本的な使い方
IDを生成する
使い方は驚くほどシンプルです。nanoid() を呼び出すだけで、21文字のユニークIDが得られます。
import { nanoid } from 'nanoid'
const id = nanoid()
console.log(id) // => "V1StGXR8_Z5jdHi6B-myT"
たったこれだけです。設定も初期化も不要で、インポートしてすぐに使えます。
長さを変更する
引数に数値を渡すと、IDの長さを変更できます。
import { nanoid } from 'nanoid'
const shortId = nanoid(10)
console.log(shortId) // => "IRFa-VaY2b"
ただし、短くするほど衝突確率は上がります。「何文字なら安全か」は公式のNano ID collision calculatorで計算できるので、生成頻度に応じて適切な長さを選びましょう。
カスタムアルファベットを使う
「数字だけのIDが欲しい」「紛らわしい文字(0 と O など)を除外したい」という場合は、customAlphabet を使います。
import { customAlphabet } from 'nanoid'
// 16進数文字のみ・10文字のID生成器を作る
const hexId = customAlphabet('1234567890abcdef', 10)
console.log(hexId()) // => "4f90d13a42"
第一引数に使いたい文字セット、第二引数にデフォルトの長さを指定すると、専用のID生成関数が返ってきます。
セキュリティが不要な場面では非セキュア版を
乱数の予測不可能性が重要でない用途(Reactのkey属性など)では、さらに高速な非セキュア版も選べます。
import { nanoid } from 'nanoid/non-secure'
const id = nanoid()
暗号学的な強度はないため、セッションIDやトークンなど推測されると困る用途には絶対に使わないでください。
実践的なユースケース
1. データベースの主キーとして使う
UUIDの代わりにNano IDを主キーに使うと、URLがすっきりします。以下はPrismaでの例です。
// prisma/schema.prisma では id を String 型で定義しておきます
import { PrismaClient } from '@prisma/client'
import { nanoid } from 'nanoid'
const prisma = new PrismaClient()
async function createArticle(title: string, body: string) {
return prisma.article.create({
data: {
id: nanoid(), // => "hJ8f2K_x9QzR3mNpL5vAw"
title,
body,
},
})
}
生成されたIDはそのまま https://example.com/articles/hJ8f2K_x9QzR3mNpL5vAw のようにURLへ埋め込めます。UUIDと違ってエンコードも不要です。
2. 短縮URLサービスの短いキーを作る
短縮URLのように「短さ」が命のケースでは、customAlphabet で読み間違えやすい文字を除外しつつ、長さを絞ります。
import { customAlphabet } from 'nanoid'
// 0/O、1/l/I など紛らわしい文字を除外した8文字のキー
const generateSlug = customAlphabet(
'23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ',
8
)
const slug = generateSlug()
console.log(`https://example.com/s/${slug}`) // => "https://example.com/s/xK7mP2vB"
ユーザーが口頭で伝えたり手入力したりする可能性のあるIDでは、この「紛らわしい文字の除外」が地味に効いてきます。
3. Reactでフォーム項目を動的に管理する
動的に増減するリスト項目のkeyには、配列のインデックスではなく安定したIDを使うのがReactのベストプラクティスです。
import { useState } from 'react'
import { nanoid } from 'nanoid'
type TodoItem = {
id: string
text: string
}
export function TodoList() {
const [items, setItems] = useState<TodoItem[]>([])
const addItem = (text: string) => {
setItems((prev) => [...prev, { id: nanoid(), text }])
}
return (
<div>
<button onClick={() => addItem('新しいタスク')}>追加</button>
<ul>
{items.map((item) => (
<li key={item.id}>{item.text}</li>
))}
</ul>
</div>
)
}
インデックスをkeyにすると項目の削除や並べ替えで表示が崩れることがありますが、Nano IDなら項目ごとに不変のIDが割り当てられるため安心です。
4. アップロードファイルの一意なファイル名を作る
ファイル名の衝突を避けたいときにも便利です。
import { nanoid } from 'nanoid'
import path from 'node:path'
function buildUploadFileName(originalName: string) {
const ext = path.extname(originalName) // 例: ".png"
return `${Date.now()}-${nanoid(12)}${ext}`
}
console.log(buildUploadFileName('photo.png'))
// => "1752384000000-mJ8xK2_p9QzR.png"
タイムスタンプと組み合わせれば、時系列ソートのしやすさと一意性を両立できます。
UUIDとの使い分け
「結局、UUIDとどちらを使えばいいの?」という疑問にお答えすると、判断基準は次のとおりです。
- Nano IDが向いているケース - URLに含めるID、フロントエンドでの生成、バンドルサイズを抑えたいSPA、文字数を柔軟に調整したい場合
- UUIDが向いているケース - RFC 9562準拠が求められるシステム間連携、データベースのネイティブUUID型(PostgreSQLの
uuid型など)をそのまま活かしたい場合
安全性(衝突確率・乱数品質)はどちらも同等なので、「規格への準拠が必要かどうか」と「短さが嬉しいかどうか」で選ぶとよいでしょう。
まとめ
今回は軽量ユニークID生成ライブラリ「Nano ID」を紹介しました。
- わずか118バイト・依存ゼロの超軽量ライブラリで、
nanoid()の1行でUUIDと同等の安全性を持つIDを生成できます - デフォルトで21文字・URLフレンドリーな文字セットなので、そのままURLやファイル名に使えます
customAlphabetを使えば、文字セットと長さを用途に合わせて自由に調整できます- データベースの主キー、短縮URL、Reactのkey属性、ファイル名生成など、活躍の場は多岐にわたります
「IDの生成方法なんてどれも同じ」と思っていた方こそ、一度Nano IDを触ってみてください。導入コストはほぼゼロなのに、URLの見た目やバンドルサイズという日々の開発体験が確実に良くなります。まずは手元のプロジェクトで npm install nanoid から始めてみましょう。