TL;DR
以下の形でインポートする。
import { webcrypto as crypto } from "crypto";
または、 Node.js を v19 以降にアップグレードする。
問題:Next.js App Route で Web Crypto API が使えない
Next.js v13 にて、 App Route を使っていた。
Web Crypto API、特に SubtleCrypto
を使用したコードを書いたところ、以下のように undefined
とエラーが出た。
TypeError: Cannot read properties of undefined (reading 'digest')
92| const hash = await crypto.subtle.digest("SHA-1", arr);
原因:Node バージョンまたは Next.js ランタイムの違い
v19 以前の Node.js では Web Crypto API は実験機能であり、明示的に有効化しない限りグローバル this には含まれないらしい。
また、 Next.js リポジトリ内の issue と App Router のドキュメント によると、 App Route ではデフォルトで Node.js ランタイムが使われるとのこと。
解決:明示的にインポートする
issue では Next.js のランタイムを "edge"
に指定することで Web Crypto API を使用可能にしていた。
しかし、上で挙げた App Router のドキュメントにあるとおり、 Edge ランタイムはパフォーマンスや利用可能な Node.js API に違いがある。
また、 globalThis.crypto
の存在を確認して代入する方法も紹介されているが、今回は一つの TS ファイル内で使えれば良かったので、そこまでしなくても良かった。
import crypto from "node:crypto"
globalThis.crypto ??= crypto.webcrypto
そこで、上記のコードを参考にし、 crypto.webcrypto
そのものを単にインポートすることにした。
import { webcrypto as crypto } from "crypto";
Node.js のバージョンをあげることでも解決可能
先述の通り Node.js 19+ では標準で Web Crypto API を使用可能なので、 Node.js を v19 以降にアップグレードすることでも解決可能。