JavaScriptでUUID v4を生成する方法オンライン
無料の UUID v4ジェネレーター をブラウザで直接使用 — インストール不要。
UUID v4ジェネレーター をオンラインで試す →JavaScript アプリケーションは必ずユニーク識別子を必要とします — セッショントークン、データベース行、 決済 API の冪等性キー、分散トレーシングの相関 ID など。今日 JavaScript で UUID v4 を生成する最もシンプルな方法は crypto.randomUUID() です: 依存関係ゼロ、1 行、暗号論的に安全。UUID v4 はサービス間の調整が不要なため広く使われています — クライアントとサーバーが衝突リスクなしに独立して ID を生成できます。 このガイドでは、その組み込み API、 uuid npm パッケージ、 バリデーションをすべて Node.js 19+ とモダンブラウザで解説します。コード不要な選択肢として、 ToolDeck の UUID v4 ジェネレーター で即座に準拠した識別子を生成できます。
- ✓crypto.randomUUID() はブラウザと Node.js に組み込まれています — 依存関係ゼロ、1 行のコードで使えます。
- ✓UUID v4 は 128 ビットのランダム識別子です:xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx(y は 8、9、a、または b)。
- ✓/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i で検証 — バージョンとバリアントビットを確認します。
- ✓uuid npm パッケージはランダム ID 以上が必要なときに v1、v3、v5、v7 サポートを追加します。
- ✓データベース主キーには UUID v4(ランダム)より UUID v7(時刻順)を推奨します。インデックスの断片化を減らせます。
UUID v4 とは?
UUID(Universally Unique Identifier)バージョン 4 は、4 つのハイフンで区切られた 32 桁の16進数からなる 128 ビットのランダム識別子です: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx。 15 番目の位置にある 4 はバージョンを示します。 20 番目の位置にある y は 8、 9、 a、または b のいずれかです(RFC 4122 バリアント)。 残りの 122 ビットはランダムです。UUID v4 はシステム間の調整が不要なため JavaScript アプリケーションで最も広く使われているバージョンです — クライアントとサーバーが衝突を心配することなく独立して ID を生成できます。
// 識別子なし
const event = { action: "user.login", ts: 1711824000 };// UUID v4 を付与
const event = {
id: "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
action: "user.login",
ts: 1711824000
};crypto.randomUUID() — JavaScript ネイティブアプローチ
crypto.randomUUID() は Chrome 92+、Firefox 95+、Safari 15.4+、および Node.js 19+(Node.js 14.17.0 から globalThis.crypto 経由で実験的サポート)で利用可能です。 小文字の 36 文字 UUID v4 文字列を返します。ブラウザ JavaScript ではインポート不要です。 Node.js ではグローバルの crypto オブジェクトで直接呼び出すか、 node:crypto モジュールから明示的にインポートすることもできます。
// モダンブラウザで動作 — ビルドステップ不要、バンドラー不要
const requestId = crypto.randomUUID();
console.log(requestId);
// "3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f"
// ユニーク識別子が必要な場所で使用
const telemetryEvent = {
event_id: crypto.randomUUID(),
action: "checkout.started",
session_id: crypto.randomUUID(),
timestamp: Date.now(),
cart_total_cents: 14999,
};
console.log(JSON.stringify(telemetryEvent, null, 2));// アプローチ 1: グローバル crypto(Node.js 19+)
const orderId = crypto.randomUUID();
console.log(orderId);
// "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d"
// アプローチ 2: node:crypto から明示的にインポート
import { randomUUID } from 'node:crypto';
const correlationId = randomUUID();
console.log(correlationId);
// "f7e6d5c4-b3a2-4190-8f7e-6d5c4b3a2190"コードが古いブラウザや組み込み WebView で実行される可能性がある場合、 crypto.randomUUID の機能検出を行うことをお勧めします。チェックは単一の typeof ガードで済みます:
function generateUUIDv4() {
// 利用可能なときはネイティブ API を優先
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
return crypto.randomUUID();
}
// getRandomValues を使った手動フォールバック(次のセクション参照)
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
// バージョン(4)とバリアント(RFC 4122)を設定
bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4
bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant 10xx
const hex = [...bytes].map(b => b.toString(16).padStart(2, '0'));
return [
hex.slice(0, 4).join(''),
hex.slice(4, 6).join(''),
hex.slice(6, 8).join(''),
hex.slice(8, 10).join(''),
hex.slice(10, 16).join(''),
].join('-');
}
console.log(generateUUIDv4());
// "9b2e4f1a-7c3d-4e8f-a5b6-0d2c1e9f8a7b"crypto.randomUUID() は常に利用可能です。一部のブラウザでは 非セキュアな HTTP ページで例外をスローします。開発中にアプリがプレーン HTTP で実行される可能性がある場合、 上記の getRandomValues フォールバックがそのケースに対応します。ライブラリなしで UUID v4 を生成する
crypto.randomUUID() に 依存できない場合があります — crypto API を 削除した WebView を対象にしている場合や、内部動作を理解したい場合などです。手動アプローチでは crypto.getRandomValues() (IE 11 以降で利用可能)を使用して 16 バイトにランダムデータを格納し、 2 つのビットマスク操作でバージョンとバリアントフィールドを設定します。 この 2 つの操作が UUID v4 と純粋なランダムバイト列との唯一の違いです。
function uuidv4Manual() {
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
// バージョンを設定: バイト 6 のビット 12–15 = 0100(バージョン 4)
bytes[6] = (bytes[6] & 0x0f) | 0x40;
// バリアントを設定: バイト 8 のビット 6–7 = 10(RFC 4122)
bytes[8] = (bytes[8] & 0x3f) | 0x80;
const hex = [...bytes].map(b => b.toString(16).padStart(2, '0'));
return (
hex.slice(0, 4).join('') + '-' +
hex.slice(4, 6).join('') + '-' +
hex.slice(6, 8).join('') + '-' +
hex.slice(8, 10).join('') + '-' +
hex.slice(10, 16).join('')
);
}
const traceId = uuidv4Manual();
console.log(traceId);
// "e4d7c2a1-3f9b-48e5-a612-9d8c7b6a5f4e"
// UUID v4 バリデーションをパスするか確認
const UUID_V4_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
console.log(UUID_V4_RE.test(traceId)); // trueMath.random() を絶対に使用しないでください。暗号論的に安全ではなく、 出力の周期が短すぎ、一部のエンジンでは予測可能なシーケンスを生成します。常に crypto.getRandomValues() または crypto.randomUUID() を使用してください。uuid npm パッケージ — マルチバージョンサポート
npm の uuid パッケージは crypto.randomUUID() が存在する前から JavaScript の定番 UUID ライブラリです。 以下の 3 つの状況では依然として有用です:v4 以外の UUID バージョン(v1、v3、v5、v7)が必要な場合、 Node.js 14.17.0 より古いランタイムを対象にしている場合、または validate や parse ユーティリティ関数が必要な場合です。モダンランタイムでの単純な UUID v4 生成であれば、ネイティブ API で十分であり、 依存関係は追加しないほうがよいでしょう。
npm install uuid
import { v4 as uuidv4, validate, version } from 'uuid';
// UUID v4 を生成
const paymentId = uuidv4();
console.log(paymentId);
// "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed"
// 任意の UUID 文字列を検証
console.log(validate(paymentId)); // true
console.log(validate("not-a-uuid")); // false
// UUID のバージョンを検出
console.log(version(paymentId)); // 4
// テストデータベースのシード用にバッチ生成
const testAccounts = Array.from({ length: 5 }, () => ({
account_id: uuidv4(),
plan: "starter",
created_at: new Date().toISOString(),
}));
console.log(testAccounts);uuid パッケージはブラウザでは内部的に crypto.getRandomValues()、Node.js では crypto.randomBytes() を使用しているため、 エントロピーソースはネイティブ API と同一です。違いは追加のユーティリティ関数と マルチバージョンサポートのみです。コードをまったく書きたくない場合は、 UUID v4 ジェネレーター をお試しください — ブラウザ上でワンクリックで RFC 4122 準拠の v4 識別子を生成できます。
決定論的 UUID — 文字列から UUID v5 を生成する
UUID v4 は定義上ランダムです — 2 回呼び出すと必ず異なる結果を返します。 逆が必要な場合もあります:同じ入力文字列が常に同じ UUID を生成すべき場合です。 それが UUID v5 です。ネームスペース UUID と入力文字列を SHA-1 でハッシュし、 結果を UUID としてフォーマットします。 同じネームスペース + 同じ入力 = どのマシンでも毎回同じ出力になります。 これは URL、メールアドレス、またはリソースを識別する任意の文字列から安定した ID を導出するのに役立ちます。
import { v5 as uuidv5 } from 'uuid';
// URL 用の組み込みネームスペース(RFC 4122)
const URL_NAMESPACE = uuidv5.URL;
// "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
// 同じ URL は常に同じ UUID を生成
const pageId1 = uuidv5("https://api.warehouse.dev/products/sku-7291", URL_NAMESPACE);
const pageId2 = uuidv5("https://api.warehouse.dev/products/sku-7291", URL_NAMESPACE);
console.log(pageId1 === pageId2); // true
console.log(pageId1);
// "a6e4e1c0-7e23-5d3b-8f14-9c2a1b3d5e7f"
// アプリケーション用カスタムネームスペース
const APP_NAMESPACE = "f47ac10b-58cc-4372-a567-0e02b2c3d479";
const tenantId = uuidv5("acme-corp", APP_NAMESPACE);
console.log(tenantId);
// "d4735e3a-265b-564e-8f32-7a1b2c3d4e5f"補足:UUID v3 は SHA-1 の代わりに MD5 を使用して同じことを行います。新しいプロジェクトでは v5 を推奨します。 MD5 には既知の衝突の弱点がありますが、ID 生成においては大きな問題ではないものの、 両方が利用可能な場合に MD5 を選ぶ理由はありません。
crypto.randomUUID() および関連 API リファレンス
ネイティブの crypto.randomUUID() は引数を取りません — 文字列を返すだけです。依存関係ゼロで RFC 4122 準拠の識別子が必要な場合に使用します。 フォーマット済み UUID 文字列の代わりに生のランダムバイトが必要な場合(例えば型付き配列に格納したり、 鍵を導出したりする場合)は crypto.getRandomValues() を直接使用してください。UUID 作業で重要な関連 API を以下に示します。
UUID v4 正規表現パターンの内訳:
正規表現で UUID v4 を検証する
文字列が正しい UUID v4 かどうかの検証は常に必要です — 受信 API リクエストボディ、 URL パラメーター、Webhook ペイロードなど。依存関係ゼロで v4 のみを検証する場合は 手書きの正規表現が適切な選択です。すでに uuid パッケージを使用している場合は、すべての UUID バージョンに対応しカスタムパターンのメンテナンスより エラーが少ない validate() エクスポートを優先してください。正規表現 /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i はバージョンニブル( 4 であること)と バリアントニブル( 8、 9、 a、または b であること)の両方をチェックします。 ブール値チェックには RegExp.prototype.test() を、 テキストから UUID を抽出するには .match() を使用してください。
const UUID_V4_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
function isUUIDv4(str) {
return UUID_V4_RE.test(str);
}
// 有効な UUID v4
console.log(isUUIDv4("9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d")); // true
// UUID v1 — バージョンニブルが 4 ではなく 1
console.log(isUUIDv4("550e8400-e29b-11d4-a716-446655440000")); // false
// UUID v7 — バージョンニブルが 7
console.log(isUUIDv4("018e4a0c-5b3f-7d12-8a9b-0c1d2e3f4a5b")); // false
// 不正な文字列
console.log(isUUIDv4("not-a-uuid")); // false
console.log(isUUIDv4("")); // false
console.log(isUUIDv4("9b1deb4d3b7d4bad9bdd2b0d7b3dcb6d")); // false(ハイフンなし)
// 大きな文字列から UUID を抽出
const logLine = 'Request req_id=9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d failed with 503';
const match = logLine.match(/[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i);
console.log(match?.[0]);
// "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"ファイルと API レスポンスへの UUID 付与
実際には crypto.randomUUID() を単独で呼び出すことはほとんどありません。よく見られるパターンが 2 つあります: データベースに書き込む前にレコードに ID を割り当てることと、 ログでサービス間のリクエストを追跡できるよう送信 API リクエストに相関 ID を付与することです。
NDJSON ファイル読み込み → UUID 割り当て → 書き戻し
import { readFileSync, writeFileSync } from 'node:fs';
import { randomUUID } from 'node:crypto';
function assignIds(inputPath, outputPath) {
const lines = readFileSync(inputPath, 'utf-8')
.split('\n')
.filter(line => line.trim());
const records = lines.map(line => {
try {
const record = JSON.parse(line);
if (!record.id) {
record.id = randomUUID();
}
return JSON.stringify(record);
} catch (err) {
console.error(`不正な行をスキップ: ${err.message}`);
return null;
}
}).filter(Boolean);
writeFileSync(outputPath, records.join('\n') + '\n');
console.log(`${records.length} 件のレコードに ID を割り当て → ${outputPath}`);
}
assignIds('warehouse-products.ndjson', 'warehouse-products-with-ids.ndjson');
// 1284 件のレコードに ID を割り当て → warehouse-products-with-ids.ndjson送信 API リクエストへの相関 ID 付与
import { randomUUID } from 'node:crypto';
async function createShipment(orderPayload) {
const correlationId = randomUUID();
try {
const response = await fetch('https://api.logistics.dev/v2/shipments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Correlation-ID': correlationId,
'X-Idempotency-Key': randomUUID(),
},
body: JSON.stringify(orderPayload),
});
if (!response.ok) {
const errorBody = await response.text();
throw new Error(`Shipment API returned ${response.status}: ${errorBody}`);
}
const result = await response.json();
console.log(`配送作成: ${result.shipment_id} (相関ID: ${correlationId})`);
return result;
} catch (err) {
console.error(`[correlation:${correlationId}] 配送失敗: ${err.message}`);
throw err;
}
}
await createShipment({
order_id: "ord_8a3f91bc",
destination: { city: "東京", state: "東京都", zip: "100-0001" },
items: [{ sku: "WH-7291", quantity: 2, weight_kg: 1.4 }],
});コマンドラインでの UUID 生成
スクリプトは常に必要ではありません。Node.js はコマンドラインから直接 UUID を生成でき、 シェルスクリプト、CI パイプライン、素早いアドホックテストに便利です。 -e フラグは 1 つの式を評価します。
# 1 つの UUID node -e "console.log(crypto.randomUUID())" # 3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f # 5 つの UUID を一度に生成 node -e "for(let i=0;i<5;i++) console.log(crypto.randomUUID())" # 生成してシェル変数に代入 export REQUEST_ID=$(node -e "process.stdout.write(crypto.randomUUID())") echo "Request ID: $REQUEST_ID" # npx uuid を使用(グローバルインストール済みまたは1回限りの場合) npx uuid v4 # 1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed
# 任意のブラウザの DevTools コンソールを開いて入力: crypto.randomUUID() # "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
uuidgen は macOS と多くの Linux ディストリビューションに プリインストールされています。モダンシステムではデフォルトで UUID v4 を生成します。高性能な代替手段 — nanoid
1 秒間に何千もの ID を生成する必要があり、36 文字の UUID 形式が必須要件でない場合は、 nanoid を検討してください。 uuid.v4() の 2 倍速く、デフォルトで 21 文字の URL セーフ ID を生成し、ミニファイ後約 1 KB です。 出力は UUID ではなくカスタムアルファベット ID であるため、RFC 4122 準拠が必要な場所 (データベースの UUID カラム、UUID 形式を検証する API、OpenTelemetry トレース ID)では使用しないでください。 ただし内部の相関 ID、React コンポーネントキー、URL スラッグには適しています。
npm install nanoid
import { nanoid, customAlphabet } from 'nanoid';
// デフォルト: 21 文字の URL セーフ ID(A-Za-z0-9_-)
const trackingCode = nanoid();
console.log(trackingCode);
// "V1StGXR8_Z5jdHi6B-myT"
// カスタム長
const shortCode = nanoid(10);
console.log(shortCode);
// "IRFa-VaY2b"
// カスタムアルファベット — 数字のみ、12 桁
const numericId = customAlphabet('0123456789', 12);
console.log(numericId());
// "839274651023"
// カスタムアルファベット — 16進数のみ、32 文字(ハイフンなし UUID v4 と同等のエントロピー)
const hexId = customAlphabet('0123456789abcdef', 32);
console.log(hexId());
// "4f8a1b2c3d7e9f0a5b6c8d1e2f3a4b5c"ターミナル出力のシンタックスハイライト
UUID が多用されるアプリケーションのデバッグでは、ターミナルで16進数の文字列を大量に眺めることになります。 色付けが役立ちます。 chalk ライブラリ(または Node.js 21.7+ の新しい組み込み node:util styleText)を使用すると、ログ出力で UUID を周囲のテキストから目立たせることができます。
import chalk from 'chalk';
import { randomUUID } from 'node:crypto';
function logEvent(action, metadata = {}) {
const eventId = randomUUID();
const timestamp = new Date().toISOString();
console.log(
chalk.gray(timestamp),
chalk.cyan(eventId),
chalk.white(action),
Object.keys(metadata).length
? chalk.dim(JSON.stringify(metadata))
: ''
);
}
logEvent('shipment.created', { order_id: 'ord_8a3f', carrier: 'fedex' });
logEvent('payment.captured', { amount_cents: 14999, currency: 'USD' });
logEvent('webhook.delivered', { endpoint: 'https://hooks.acme.dev/orders' });
// 2026-03-27T10:15:00.000Z a1b2c3d4-... shipment.created {"order_id":"ord_8a3f",...}JavaScript で短いユニーク ID を生成する
36 文字の UUID は長すぎる場合があります — URL スラッグ、QR コードデータ、SMS メッセージ、 組み込みハードウェアプロトコルはすべて長さの制約があります。
import { randomUUID } from 'node:crypto';
// 1. UUID v4 からハイフンを除去 → 32 文字の16進数文字列
const hex32 = randomUUID().replaceAll('-', '');
console.log(hex32);
// "3e7f1a924b0c4d8e9f127a6b3c8d5e1f"(32 文字)
// 2. 16 バイトのランダム値を Base64 エンコード → 22 文字(URL セーフ)
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
const base64Id = Buffer.from(bytes)
.toString('base64url')
.replace(/=+$/, '');
console.log(base64Id);
// "Pj8akksNTY6fEnarPIvR"(22 文字、128 ビットのエントロピー)
// 3. カスタム長の nanoid
import { nanoid } from 'nanoid';
const short12 = nanoid(12);
console.log(short12);
// "V1StGXR8_Z5j"(12 文字、約 71 ビットのエントロピー)衝突確率の計算:12 文字の nanoid(デフォルトアルファベット 64 文字)は約 71 ビットのエントロピーを提供します。 1 秒間に 1,000 個の ID を生成する場合、衝突確率 1% に達するまでに約 116 年かかります。 ほとんどのアプリケーションには十分すぎる値です。1 日に数百万個の ID を生成する場合は、 フル UUID を使用するか、少なくとも 21 文字の nanoid を使用してください。
UUID v7 — v4 の時刻順代替
UUID v7(RFC 9562 で定義)は最初のセグメントに 48 ビットの Unix ミリ秒タイムスタンプを埋め込み、 続いてランダムビットを格納します。結果は v4 に似た UUID ですが時系列にソートされます。 これによりデータベース主キーとして v4 より優れた選択肢となります: 新しい行がランダムな位置ではなく常に B ツリーインデックスの末尾に追加されるため、 ページ分割と断片化が減少します。Postgres テーブルで時刻順 ID が必要なプロジェクトでは、 すぐに v7 に切り替えます — 大規模ではインデックスパフォーマンスの差が顕著です。ToolDeck の UUID v7 ジェネレーター では任意の v7 UUID の埋め込みタイムスタンプを確認できます。
import { v7 as uuidv7 } from 'uuid';
// 3 つの UUID v7 値を生成 — 時系列にソートされることに注目
const id1 = uuidv7();
const id2 = uuidv7();
const id3 = uuidv7();
console.log(id1);
// "018e4a0c-5b3f-7d12-8a9b-0c1d2e3f4a5b"
console.log(id2);
// "018e4a0c-5b40-7e34-9c2d-1e4f5a6b7c8d"
console.log(id3);
// "018e4a0c-5b41-7f56-ae3f-2a5b6c7d8e9f"
// 辞書順で作成時刻によってソートされる
console.log([id3, id1, id2].sort());
// [id1, id2, id3] — 時系列順が保持される
// タイミング情報を漏らしてはいけないトークンには v4 を使用
import { v4 as uuidv4 } from 'uuid';
const sessionToken = uuidv4(); // 完全ランダム、タイミング情報なしuuid パッケージは バージョン 9.0.0 以降で v7 をサポートします。 古いバージョンを使用している場合は npm install uuid@latest を実行してアップグレードしてください。ビルドステップなしでブラウザで UUID v4 を使用する
バンドラーも npm も、トランスパイラーも不要です。ただのプレーン HTML ファイルです。 これはクライアントサイド JavaScript で UUID を生成する最もシンプルな方法です。 crypto.randomUUID() がブラウザ組み込み API であるため動作します。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><title>UUID Generator</title></head>
<body>
<p>Your UUID: <strong id="output"></strong></p>
<button onclick="document.getElementById('output').textContent = crypto.randomUUID()">
Generate
</button>
<script>
// ページ読み込み時に 1 つ生成
document.getElementById('output').textContent = crypto.randomUUID();
</script>
</body>
</html>これがファイルの全体です。CDN インポートも、ライブラリを読み込むスクリプトタグも不要です。 バッチ生成、バリデーション、決定論的 ID など、より複雑なことには uuid パッケージまたは前述の手動フォールバックが必要です。ただし素早いプロトタイプや社内ツールであれば、 これで十分です。
よくあるミス
古いブログ記事からコピーされた Math.random() UUID パターンが本番コードに入り込むのを数え切れないほど見てきました。 これらのパターンが引き起こすバグはサイレントです:ランタイムエラーは発生せず、 負荷時やセキュリティレビューで後になって表面化する微妙な不正動作が起きます。
問題: Math.random() は暗号論的に安全ではありません。一部のエンジンでは出力が予測可能で、エントロピーの低さにより適切な CSPRNG よりも衝突がはるかに発生しやすくなります。
解決策: 常に crypto.randomUUID() または crypto.getRandomValues() を使用してください。どちらもオペレーティングシステムの CSPRNG を使用します。
// 危険 — 予測可能、エントロピーが低い
function badUuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
/[xy]/g,
c => {
const r = Math.random() * 16 | 0;
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
}
);
}// 安全 — OS の CSPRNG を使用
const id = crypto.randomUUID();
// または手動フォールバックが必要な場合:
function secureUuid() {
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
bytes[6] = (bytes[6] & 0x0f) | 0x40;
bytes[8] = (bytes[8] & 0x3f) | 0x80;
const h = [...bytes].map(b => b.toString(16).padStart(2, '0'));
return `${h.slice(0,4).join('')}-${h.slice(4,6).join('')}-${h.slice(6,8).join('')}-${h.slice(8,10).join('')}-${h.slice(10).join('')}`;
}問題: crypto.randomUUID() は小文字の16進数を返しますが、他のシステム(データベース、API、ユーザー入力)からの UUID は大文字を使用することがあります。大文字・小文字が異なる場合、直接の === 比較は失敗します。
解決策: 比較前に両方を小文字に正規化してください。
const fromApi = "9B1DEB4D-3B7D-4BAD-9BDD-2B0D7B3DCB6D"; // API からの大文字
const local = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"; // crypto からの小文字
if (fromApi === local) { /* 実行されない */ }const fromApi = "9B1DEB4D-3B7D-4BAD-9BDD-2B0D7B3DCB6D";
const local = "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d";
if (fromApi.toLowerCase() === local.toLowerCase()) {
// 正しくマッチする
}問題: 一部の UUID ライブラリ(特に他の言語)は UUID オブジェクトを返します。JavaScript では UUID 文字列を誤ってオブジェクトでラップすると、等価チェック、JSON シリアライゼーション、データベースクエリが壊れます。
解決策: 常に UUID をプレーン文字列として保存・受け渡しします。ライブラリがオブジェクトを返す場合は、すぐに .toString() を呼び出すか文字列プロパティにアクセスしてください。
// 不必要なラッパーを作成
class UUID {
constructor(value) { this.value = value; }
}
const id = new UUID(crypto.randomUUID());
console.log(id === id); // true、しかし...
console.log(JSON.stringify({ id })); // {"id":{"value":"..."}}// 文字列をそのまま使用
const id = crypto.randomUUID();
console.log(JSON.stringify({ id }));
// {"id":"3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f"}問題: UUID v4 は完全にランダムです。UUID v4 でソートすると任意の順序になり、作成順にはなりません。これにより予測不可能なページネーション、混乱する管理画面、悪いデータベースインデックスパフォーマンスが発生します。
解決策: 時刻順の識別子が必要な場合は UUID v7 を使用してください。ソート順序が無関係なトークンと相関 ID には UUID v4 を維持してください。
// 悪い例: v4 をソート可能な主キーとして使用
const rows = [
{ id: crypto.randomUUID(), created: "2026-03-27" },
{ id: crypto.randomUUID(), created: "2026-03-26" },
];
rows.sort((a, b) => a.id.localeCompare(b.id));
// ソート順序はランダム — 作成日順ではないimport { v7 as uuidv7 } from 'uuid';
// 良い例: v7 は作成時刻でソートされる
const rows = [
{ id: uuidv7(), created: "2026-03-27" },
{ id: uuidv7(), created: "2026-03-26" },
];
rows.sort((a, b) => a.id.localeCompare(b.id));
// ソート順序が作成時刻と一致するcrypto.randomUUID() vs uuid vs nanoid — 比較一覧
ほとんどの JavaScript プロジェクトでは:ランタイムが十分に新しく UUID v4 のみが必要な場合は crypto.randomUUID() を使用してください。v5(決定論的)または v7(時刻順)サポートが必要な場合は uuid パッケージを使用してください。36 文字の UUID より短く URL セーフな ID が実用的な場合は nanoid を使用してください — ただし nanoid の出力は UUID 準拠ではなく、RFC 4122 形式を期待するシステムでの バリデーションは失敗することを覚えておいてください。
コード不要の代替手段として、 UUID v4 ジェネレーター でブラウザ上で即座に識別子を作成できます。既存の UUID を検査するには、 UUID デコーダー に貼り付けてバージョン、バリアント、および埋め込みタイムスタンプデータを確認してください。
よくある質問
JavaScript で UUID v4 を生成するにはどうすればよいですか?
モダンブラウザ(Chrome 92+、Firefox 95+、Safari 15.4+)または Node.js 19+ で crypto.randomUUID() を呼び出します。"3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f" のような小文字文字列を返します。ブラウザでは crypto がグローバル組み込みのためインポート不要です。Node.js では import { randomUUID } from "node:crypto" と明示的にインポートすることもできます。Node.js 19 より古いランタイムでも、Node.js 14.17.0 から実験的に crypto.randomUUID() がグローバルで利用可能です。コードを書かずに使いたい場合は、/en/uuid/v4 の UUID v4 ジェネレーターでワンクリックして準拠した識別子を生成できます。
const sessionId = crypto.randomUUID(); console.log(sessionId); // "3e7f1a92-4b0c-4d8e-9f12-7a6b3c8d5e1f"
crypto.randomUUID() は暗号論的に安全ですか?
はい。crypto.randomUUID() は crypto.getRandomValues() と同じ CSPRNG(暗号論的擬似乱数生成器)を使用します。UUID v4 の 122 ビットのランダム値により、衝突確率は実用上無視できるほど小さく、50% の衝突確率に達するには約 27 億京(2.71 quintillion)個の UUID を生成する必要があります。エントロピーはオペレーティングシステムのランダムソース(Linux の /dev/urandom、Windows の BCryptGenRandom)から得られており、Math.random() は使用されません。Math.random() は暗号論的に安全ではありません。したがって UUID v4 の値は、予測不可能性が求められるセッショントークン、CSRF トークン、その他のセキュリティ上重要な識別子として安全に使用できます。セキュリティコンテキストで Math.random() ベースの UUID ジェネレーターを代用しないでください。
UUID v4 をデータベースの主キーとして使用できますか?
使用できますが、パフォーマンス上のトレードオフがあります。UUID v4 は完全にランダムなため、B ツリーインデックスが断片化しやすくなります。各新しい行がインデックスの末尾ではなくランダムな位置に挿入されるからです。書き込みの多いテーブルでは過剰なページ分割とキャッシュミスが発生し、INSERT および範囲スキャンのパフォーマンスが低下します。データベースがサポートしている場合(PostgreSQL、MySQL 8.0+、SQL Server)、UUID v7(時刻順)の方が主キーとして優れています。新しい行が常にインデックスの末尾に追加されるためです。UUID v4 は、セッショントークン、OAuth ステートパラメーター、冪等性キー、相関 ID、および作成時刻を隠すことが望ましいフィールドに適しています。
// UUID v4 — ランダム、ソート不可
const correlationId = crypto.randomUUID();
// UUID v7 — 時刻順、DB 主キーに適している
import { v7 as uuidv7 } from 'uuid';
const rowId = uuidv7();UUID v4 と UUID v7 の違いは何ですか?
UUID v4 は 122 ビットすべてにランダムデータを格納します。すべてのセグメントは実質的にランダムです。UUID v7(RFC 9562、2024年公開)は最初のセグメントに 48 ビットの Unix ミリ秒タイムスタンプ、2 番目のセグメントに 12 ビットのサブミリ秒精度、残りにランダムビットを格納します。どちらも合計 128 ビットで、同じ 36 文字のハイフン区切り形式を使用するため、ストレージ層では互換性があります。UUID v7 は作成時刻によって辞書順にソートでき、B ツリーインデックスをコンパクトに保ち、時間ウィンドウでの範囲クエリを効率化します。ID が作成時刻を公開してはならない場合(タイミング情報が悪用される可能性がある公開向けトークンなど)は UUID v4 を、データベース主キー・監査ログ・イベントストリームなど時系列順が重要な場合は UUID v7 を選択してください。
JavaScript で UUID v4 文字列を検証するにはどうすればよいですか?
/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i の正規表現でテストします。15 番目の位置(0 インデックス)にあるリテラル "4" がバージョンニブルを確認し、20 番目の位置にある文字(8、9、a、b のいずれか)が RFC 4122 バリアントビットをエンコードしています。この正規表現は UUID v1、v7、および不正な文字列を正しく拒否します。i フラグによって大文字・小文字を区別しないため、他のシステムからの大文字の16進数もノーマライズなしで検証をパスします。バージョンに関係なく有効な UUID かどうかだけを確認したい場合は、より緩いパターン /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i を使用してください。
const UUID_V4_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
UUID_V4_RE.test("550e8400-e29b-41d4-a716-446655440000"); // true
UUID_V4_RE.test("550e8400-e29b-11d4-a716-446655440000"); // false (v1)
UUID_V4_RE.test("not-a-uuid"); // falseJavaScript で短いユニーク ID を生成するにはどうすればよいですか?
UUID v4 からハイフンを取り除くことで 32 文字の16進数文字列を得られます:crypto.randomUUID().replaceAll("-", "")。さらに短くしたい場合は nanoid を使用してください。デフォルトで 21 文字の URL セーフ ID(A–Z、a–z、0–9、_ と -)を生成し、フル UUID と同等の衝突耐性があります。トレードオフは明確です。短い ID は衝突確率が高くなりますが、21 文字の nanoid は 126 ビットのエントロピーを提供し、ほぼすべての実用的なアプリケーションには十分です。URL スラッグや QR コードペイロードでは、典型的な生成レートで衝突確率が懸念される前の最短で 10〜12 文字まで短縮できます。生の UUID を Base64 エンコードして切り捨てることは避けてください。切り捨てによってビットの統計的独立性が損なわれ、衝突の推測が困難になります。
// UUID v4 から 32 文字の16進数文字列を生成
const hexId = crypto.randomUUID().replaceAll('-', '');
// "3e7f1a924b0c4d8e9f127a6b3c8d5e1f"
// nanoid で 21 文字の URL セーフ ID を生成
import { nanoid } from 'nanoid';
const shortId = nanoid();
// "V1StGXR8_Z5jdHi6B-myT"関連ツール
Sophie is a full-stack developer focused on TypeScript across the entire stack — from React frontends to Express and Fastify backends. She has a particular interest in type-safe API design, runtime validation, and the patterns that make large JavaScript codebases stay manageable. She writes about TypeScript idioms, Node.js internals, and the ever-evolving JavaScript module ecosystem.
Marcus specialises in JavaScript performance, build tooling, and the inner workings of the V8 engine. He has spent years profiling and optimising React applications, working on bundler configurations, and squeezing every millisecond out of critical rendering paths. He writes about Core Web Vitals, JavaScript memory management, and the tools developers reach for when performance really matters.