🎲

crypto.randomUUIDをブラウザとサーバーとNext.jsのミドルウェアで使用するサンプルコード

2024/05/08に公開

cryptorandomUUIDを使えばuuidを生成できます。
開発においてモノレポ構成をとっており、どうせならuuidを生成するコードを、ブラウザとサーバーサイドで統一しようと思ったところ、思った以上に難しかったためサンプルコードを共有します。

おさらい

nodejs環境でcrypto.randomUUIDを使用する

nodejs環境でのcrypto利用方法。requireもしくはimportします。randomUUIDAPI自体はnodeのv14.17v15.6から使用できます

const crypto = require('crypto');

crypto.randomUUID();

ブラウザ環境でcypto.randomUUIDを使用する

ブラウザ環境ではグローバルにcryptoを利用できます

crypto.randomUUID();

Next.jsでcypto.randomUUIDを使用する

Next.jsには2つのランタイム環境が共存します。middlewareはedgeランタイム環境で使用できるnodejsのAPIが制限されています。ランタイム環境の識別はprocess.env.NEXT_RUNTIMEでできます。

ややこしいことに、edgeランタイムではcrytoはグローバルで使用できます。

if(process.env.NEXT_RUNTIME === 'edge'){
  crypto.randomUUID();
} else {
  const crypto = require('crypto');
  crypto.randomUUID();
}

共通で使用想定のライブラリ

uuidからハイフンを抜いて、すべての環境で使えるように共通化したコードです。

interface CryptoType {
  randomUUID: () => string;
}

let cryptoUtil: CryptoType;

// for browser
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
  cryptoUtil = crypto as unknown as CryptoType;
} else {
  // https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation#importing-runtime-specific-code

  // for next edge runtime
  if (process.env.NEXT_RUNTIME === 'edge') {
    cryptoUtil = crypto as unknown as CryptoType;
    // for next nodejs runtime
  } else if (process.env.NEXT_RUNTIME === 'nodejs') {
    const nodeCrypto = require('crypto');
    cryptoUtil = {
      randomUUID: () => nodeCrypto.randomUUID(),
    };
    // for others (maybe server)
  } else {
    const nodeCrypto = require('crypto');
    cryptoUtil = {
      randomUUID: () => nodeCrypto.randomUUID(),
    };
  }
}

export function createUUID() {
  return cryptoUtil.randomUUID().replace(/-/g, '');
}

Discussion