5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js+Turbopack(+CloudFlare Workers)構成でsymbol-sdk v3を使えるようにする

5
Last updated at Posted at 2026-01-28

symbol-sdk v3 は WASM に強く依存しており、Next.js + Turbopack 構成でそのまま使うと Can't resolve 'fs' エラーで動作しない。
next.config.ts に2点の設定を加えることで SSR・CSR・Cloudflare Workers すべてで動作するようになる。

環境

> node -v    
v24.13.0

>npm -v
11.6.2

Next.js アプリ作成

最新のcreate-next-appからウィザード形式で作成します

mkdir your-next-proj
cd your-next-proj
npx create-next-app@latest .

オプション設定

# (任意)もしこれがでたら'y'→Enter
Need to install the following packages:
create-next-app@16.1.6
Ok to proceed? (y) y

# recommendのままEnter
? Would you like to use the recommended Next.js defaults? › - Use arrow-keys. Return to submit.
❯   Yes, use recommended defaults - TypeScript, ESLint, Tailwind CSS, App Router
    No, reuse previous settings
    No, customize settings

必要なパッケージのインストール

symbol-sdk v3とsymbol-crypto-wasm-webをインストールします

npm i symbol-sdk@^3 symbol-crypto-wasm-web

ここまでの各パッケージのバージョンの確認

  "dependencies": {
    "next": "16.2.6",
    "react": "19.2.4",
    "react-dom": "19.2.4",
    "symbol-crypto-wasm-web": "^0.1.1",
    "symbol-sdk": "^3.3.1"
  }

サンプルページ

ページに適当にsdkを呼ぶ処理を記述します。
今回はSSR,CSR双方で動くことを確認したいので以下の3つを作ります。

  • app/page.tsx:ルート(リンクのみ)
  • app/ssr/page.tsx:SSR用の検証ページ
  • app/csr/page.tsx:CSR用の検証ページ

app/page.tsx

export default function Home() {
  return (
    <main className="min-h-screen p-8">
      <h1 className="text-2xl font-semibold">Repro Index</h1>
      <p className="mt-2 text-sm text-zinc-600">
        Choose SSR or CSR pages to reproduce the Symbol SDK v3 behavior.
      </p>
      <ul className="mt-6 list-disc pl-6">
        <li>
          <a className="text-blue-600 underline" href="/ssr">
            SSR page
          </a>
        </li>
        <li>
          <a className="text-blue-600 underline" href="/csr">
            CSR page
          </a>
        </li>
      </ul>
    </main>
  );
}

app/ssr/page.tsx

import { PrivateKey } from "symbol-sdk";
import { KeyPair, SymbolFacade } from "symbol-sdk/symbol";

export default function SsrPage() {
  const facade = new SymbolFacade("testnet");

  const privateKey = PrivateKey.random();
  const account = facade.createAccount(privateKey);
  const addressRaw = account.address.toString();
  const keyPair = new KeyPair(privateKey);
  const publicKeyHex = keyPair.publicKey.toString();

  return (
    <main className="min-h-screen p-8">
      <h1 className="text-2xl font-semibold">SSR</h1>
      <ul className="mt-6 list-disc pl-6">
        <li>Address: {addressRaw}</li>
        <li>Public Key: {publicKeyHex}</li>
      </ul>
    </main>
  );
}

app/csr/page.tsx

"use client";

import { PrivateKey } from "symbol-sdk";
import { KeyPair, SymbolFacade } from "symbol-sdk/symbol";

export default function SsrPage() {
  const facade = new SymbolFacade("testnet");

  const privateKey = PrivateKey.random();
  const account = facade.createAccount(privateKey);
  const addressRaw = account.address.toString();
  const keyPair = new KeyPair(privateKey);
  const publicKeyHex = keyPair.publicKey.toString();

  return (
    <main className="min-h-screen p-8">
      <h1 className="text-2xl font-semibold">SSR</h1>
      <ul className="mt-6 list-disc pl-6">
        <li>Address: {addressRaw}</li>
        <li>Public Key: {publicKeyHex}</li>
      </ul>
    </main>
  );
}

動作確認(コケます)

  1. 開発サーバ起動
npm run dev
  1. http://localhost:3000/ にアクセス
  2. CSRまたはSSRのリンククリック

これだけだとそれぞれのページでただしくSDKを呼べずに以下のようになると思います。

image.png

エラーログ(テキスト)
Module not found: Can't resolve 'fs'
./node_modules/symbol-crypto-wasm-node/symbol_crypto_wasm.js (250:15)

Module not found: Can't resolve 'fs'
  248 |
  249 | const path = require('path').join(__dirname, 'symbol_crypto_wasm_bg.wasm');
> 250 | const bytes = require('fs').readFileSync(path);
      |               ^^^^^^^^^^^^^
  251 |
  252 | const wasmModule = new WebAssembly.Module(bytes);
  253 | const wasmInstance = new WebAssembly.Instance(wasmModule, imports);

Import traces:
  Client Component Browser:
    ./node_modules/symbol-crypto-wasm-node/symbol_crypto_wasm.js [Client Component Browser]
    ./node_modules/symbol-sdk/src/impl/ed25519_wasm.js [Client Component Browser]
    ./node_modules/symbol-sdk/src/impl/ed25519.js [Client Component Browser]
    ./node_modules/symbol-sdk/src/symbol/KeyPair.js [Client Component Browser]
    ./node_modules/symbol-sdk/src/symbol/index.js [Client Component Browser]
    ./app/csr/page.tsx [Client Component Browser]
    ./app/csr/page.tsx [Server Component]

  Client Component SSR:
    ./node_modules/symbol-crypto-wasm-node/symbol_crypto_wasm.js [Client Component SSR]
    ./node_modules/symbol-sdk/src/impl/ed25519_wasm.js [Client Component SSR]
    ./node_modules/symbol-sdk/src/impl/ed25519.js [Client Component SSR]
    ./node_modules/symbol-sdk/src/symbol/KeyPair.js [Client Component SSR]
    ./node_modules/symbol-sdk/src/symbol/index.js [Client Component SSR]
    ./app/csr/page.tsx [Client Component SSR]
    ./app/csr/page.tsx [Server Component]

https://nextjs.org/docs/messages/module-not-found

next.config.ts(js)の修正

webpackの場合

以前のwebpackを使ってるNext.jsのバージョンでは以下のやり方で動作するようです。

※一時期devだけturbopack, 本番ビルドはwebpackな時代もあったと思うのですがそれは未検証

Turbopackの場合(今回)

上記と若干書き方が違います。

next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  reactStrictMode: true,

  /**
   * bitcore 系は bundle すると versionGuard により二重ロード扱いで落ちるため external 化する。
   * symbol-sdk は WASM alias を効かせる必要があるため external 化しない。
   */
  serverExternalPackages: ["bitcore-lib", "bitcore-mnemonic"],

  /**
   * Cloudflare Workers では fs / __dirname 前提の Node 版 WASM loader が使えないため、
   * ESM import で WASM を扱う Web 版に差し替える。
   */
  turbopack: {
    resolveAlias: {
      "symbol-crypto-wasm-node": "symbol-crypto-wasm-web/symbol_crypto_wasm.js",
    },
  },
};

export default nextConfig;

※上記のように修正してもエラーが出る場合は一旦 npm run dev を止めて再実行してください。

本番ビルドでも確認

以下のコマンドで本番ビルド&起動したURLにアクセスしても動作することを確認します。

npm run build
npm run start

まとめ

symbol-crypto-wasm-nodesymbol-crypto-wasm-web への alias 差し替えと、bitcore 系の external 化の2点が要点。
Webpack 構成とは書き方が異なるため、Turbopack 移行時は turbopack.resolveAlias を使うこと。

5
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?