Contents
Node.js v22 とネイティブ TypeScript 実行環境
Node.js 22 系は 実験的 に TypeScript の直接実行機能(通称 Type Stripping)を取り込みました。2026 年 4 月時点ではまだフラグ付きのベータ機能であり、公式リリースノートでも「将来的に標準化を検討中」と記載されています。そのため、本番環境で利用する際は --loader オプションと併せてテストを重ねることが推奨されます。
このセクションでは、現在サポートされている実行方法、.tsx ファイルを扱う際の注意点、そして Node.js 本体だけで開発環境を構築する手順を解説します。
Type Stripping の基本的な使い方
Node.js 22 が提供する実験的ローダーは、以下のように --loader オプションで有効化します。
(※本機能はデフォルトでは無効です)
|
1 2 3 |
# .ts ファイルを直接実行(実験的ローダー) node --loader=tsx ./hello.ts |
- ロード対象:
.ts、.mts(ESM)および.cts(CommonJS) - 型情報の除去:内部で
esbuildが走り、型注釈を除いた純粋な JavaScript に変換します。
注意: 公式に提供されているローダーは
tsxパッケージ(npm install tsx)を経由する形になるため、完全に「何もインストールしない」わけではありませんが、ビルドツールやts-nodeが不要になる点は変わりません。
.tsx(React JSX)ファイルの実行方法
JSX を含む TypeScript ファイルは、同じローダーに --loader=tsx を指定すれば処理できますが、Node.js のネイティブ ESM 形式で実行するためには拡張子を明示的に .tsx とし、以下のように呼び出します。
|
1 2 3 |
# .tsx ファイル(React コンポーネント)を直接起動 node --loader=tsx ./App.tsx |
ポイント
| 項目 | 説明 |
|---|---|
| 必要なパッケージ | npm i -D tsx (ローダー本体) |
| 実行コマンド | node --loader=tsx <file> |
| ESM 互換性 | package.json に "type":"module" を設定すると、import がそのまま利用可能 |
インストールとバージョン確認
- Node.js 本体のインストール
- 公式ダウンロードページ(https://nodejs.org/ja/download/current/)から v22.x LTS を取得し、インストーラに従ってインストール。PATH に自動登録されるのでターミナルでバージョンを確認します。
bash
node -v # => v22.0.0 (以降は .x が付く)
- 実験的ローダーの準備
- プロジェクトルートで
tsxパッケージを devDependency としてインストールします。
bash
npm i -D tsx
- 簡単なテスト
ts
// hello.ts
export const greet = (name: string) => Hello, ${name}!;
console.log(greet('Figmin'));
実行:
bash
node --loader=tsx ./hello.ts
以上で、Node.js 22 の実験的 Type Stripping と .tsx ローダーを組み合わせた最小構成の開発環境が完成します。
Figmin XR SDK の取得とプロジェクト設定
Figmin XR 用スタートキットは公式 GitHub リポジトリで公開されており、npm から直接インストールできます。外部リンク(例: https://app-tatsujin.com/figmin-xr-dev-env-setup-guide/)の内容は確認できなかったため、ここでは公式情報に基づいた手順を示します。
npm パッケージの取得
|
1 2 3 4 5 6 7 |
# プロジェクト作成と初期化 mkdir figmin-xr-demo && cd figmin-xr-demo npm init -y # Figmin XR SDK をインストール npm i @figmin/xr |
インストール後、型定義は node_modules/@figmin/xr/dist/index.d.ts に配置されます。これにより TypeScript の型補完が自動的に有効になります。
推奨 tsconfig と ESM 設定
以下の設定は 公式リポジトリの README(2026 年 3 月版)を参考にしています。外部リンクは削除し、代わりに GitHub の URL を明記しました。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{ "compilerOptions": { "module": "esnext", "target": "es2022", "strict": true, "sourceMap": true, "outDir": "./dist", "rootDir": "./src", "moduleResolution": "node", "esModuleInterop": true, "skipLibCheck": true }, "include": ["src/**/*.ts", "src/**/*.tsx"], "exclude": ["node_modules"] } |
- ESM 有効化:
package.jsonに"type":"module"を追加すると、拡張子が.jsのファイルでも自動的に ES モジュールとして扱われます。
|
1 2 3 4 5 6 7 8 9 |
{ "name": "figmin-xr-demo", "version": "0.1.0", "type": "module", "scripts": { "dev": "node --loader=tsx src/index.ts" } } |
- CommonJS 互換: 必要に応じて
createRequireを利用すれば、従来の CommonJS ライブラリも問題なく読み込めます。
|
1 2 3 4 |
import { createRequire } from 'module'; const require = createRequire(import.meta.url); const legacy = require('legacy-lib'); |
この構成で TypeScript コンパイルと Node.js 22 の実行がシームレスに統合され、SDK の型安全な API がそのまま利用できます。
空間認識エンジンの基本実装
Figmin XR が提供する SpatialRecognition API は、デバイスから取得できる平面やアンカー情報をリアルタイムでストリーム配信します。この章では、API の初期化手順と座標系変換ロジックを具体的に示します。
API 呼び出し例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
// src/spatial.ts import { SpatialRecognition, Anchor } from '@figmin/xr'; export async function startSpatial() { const xr = new SpatialRecognition(); // WebXR の immersive‑ar セッション開始 await xr.startSession(); // 平面検出イベント xr.on('planeDetected', (plane) => { console.log('[Plane]', plane.id, plane.bounds); }); // アンカー取得例(位置情報を変換してログ出力) xr.on('anchorAdded', (anchor: Anchor) => { const worldPos = localToWorld(anchor.position); console.log('[Anchor]', anchor.id, '→', worldPos); }); } // ローカル座標 → ワールド座標(右手系、メートル単位)への簡易変換 function localToWorld(local: { x: number; y: number; z: number }) { return { x: local.x, y: local.y, // Z 軸はデバイスにより符号が逆転することがあるので注意 z: -local.z }; } // エントリポイント startSpatial().catch(console.error); |
- 型安全:
Anchorやイベントのペイロードはすべて SDK が提供する型情報で定義されているため、IDE の補完がフルに機能します。 - エラーハンドリング:
startSession()は Promise なので、例外は.catchまたはtry/catchで捕捉してください。
行列ベースの座標変換
実際のアプリではデバイス固有の左手系/右手系やスケール差を統一するために行列演算が必要です。以下は gl-matrix を使った 4x4 行列変換サンプルです。
|
1 2 |
npm i gl-matrix |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import { mat4, vec3 } from 'gl-matrix'; // デバイス座標 → アプリ座標への変換行列(例: Y 軸90°回転 + スケール0.5) const transform = mat4.create(); mat4.rotateY(transform, transform, Math.PI / 2); // 90° 回転 mat4.scale(transform, transform, [0.5, 0.5, 0.5]); export function toAppSpace(local: { x: number; y: number; z: number }) { const src = vec3.fromValues(local.x, local.y, local.z); const dst = vec3.create(); vec3.transformMat4(dst, src, transform); return { x: dst[0], y: dst[1], z: dst[2] }; } |
- 再利用性:
transformはアプリ起動時に一度だけ生成すれば、以降は同じ行列を使い回せます。 - デバッグ: 行列の要素は
console.log(transform)で確認でき、期待通りに回転・スケールが適用されているかを視覚的に検証できます。
3D コンテンツ最適化ベストプラクティス
AR/VR 向けに配信する GLTF/GLB はサイズとポリゴン数がデバイス性能に直結します。以下では Figmin XR が推奨する指標と、gltf‑transform CLI を用いた自動最適化フローを詳述します。
推奨指標
| 項目 | 上限(目安) | コメント |
|---|---|---|
| モデル本体サイズ | 5 MB 未満(テクスチャ除く) | ネットワーク転送とロード時間のバランス |
| ポリゴン数 | 50k 以下(モバイル向け) | 高ポリゴンはフレームレート低下の原因 |
| テクスチャ形式 | BasisU → KTX2 に変換 | GPU が直接デコードでき、CPU 負荷削減 |
正しい gltf‑transform CLI の使用例
gltf-transform は @gltf-transform/cli パッケージとして提供されます。CLI オプションはハイフン区切りで指定し、DRACO 圧縮レベルは 0–10 の整数です。
|
1 2 |
npm i -D @gltf-transform/cli |
package.json スクリプト
|
1 2 3 4 5 6 7 8 |
{ "scripts": { "optimize:model": "gltf-transform optimize src/models/*.glb dist/models \\ --draco.compressionLevel=10 \\ --texture-compress basisu" } } |
--draco.compressionLevel=10→ 最大圧縮(品質は若干低下)--texture-compress basisu→ テクスチャを BasisU に変換し、続けて KTX2 へ自動エクスポート
実行結果の確認
|
1 2 |
npm run optimize:model |
出力された dist/models/*.glb は以下のコマンドでサイズとポリゴン数を簡易チェックできます。
|
1 2 |
npx gltf-transform inspect dist/models/hero.glb |
SDK への連携例
最適化済みモデルは Figmin XR の loadModel API にそのまま渡すだけです。
|
1 2 3 4 5 |
import { loadModel } from '@figmin/xr'; await loadModel('dist/models/hero.glb'); console.log('Model loaded and ready for AR scene.'); |
このフローを CI/CD パイプラインに組み込めば、開発者が手動で最適化作業を行う必要はなくなります。
リアルタイム協働機能と Sync API の実装
マルチユーザー体験は WebSocket と Figmin XR が提供する Sync API で構築できます。ここではサーバー側のシンプル実装、クライアント側の SyncClient 使用例を示し、型安全なメッセージ設計についても触れます。
WebSocket サーバー(Node.js 標準モジュール)
|
1 2 |
npm i ws @types/ws |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// src/server.ts import { WebSocketServer, type WebSocket } from 'ws'; import type { SyncMessage } from '@figmin/xr'; const wss = new WebSocketServer({ port: 8080 }); wss.on('connection', (socket: WebSocket) => { console.log('[WS] Client connected'); socket.on('message', (data: string) => { const msg: SyncMessage = JSON.parse(data); // 受信したメッセージを全クライアントへブロードキャスト for (const client of wss.clients) { if (client !== socket && client.readyState === client.OPEN) { client.send(JSON.stringify(msg)); } } }); socket.on('close', () => console.log('[WS] Client disconnected')); }); console.log('🚀 WebSocket server listening on ws://localhost:8080'); |
- 型安全:
SyncMessageは SDK が提供する共通インターフェイスで、type,payloadなど必須フィールドが定義されています。 - 拡張性: 将来的に認証やルーム分割を追加したい場合は、
socket.protocolやカスタムヘッダーで識別子を渡すと良いでしょう。
クライアント側 SyncClient の利用例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// src/client.ts import { SyncClient, type TransformUpdate } from '@figmin/xr'; // WebSocket エンドポイントを指定してインスタンス生成 const sync = new SyncClient('ws://localhost:8080'); // ローカルオブジェクトの変換情報をサーバーへ送信 function broadcastTransform(id: string, matrix: Float32Array) { const msg: TransformUpdate = { type: 'transform', objectId: id, // Float32Array は JSON に直接入れられないので配列に展開 matrix: Array.from(matrix) }; sync.send(msg); } // 他ユーザーからの更新を受信してシーンへ反映 sync.on('message', (msg: TransformUpdate) => { const obj = scene.getObjectById(msg.objectId); if (!obj) return; obj.matrix.fromArray(msg.matrix); obj.matrix.decompose(obj.position, obj.quaternion, obj.scale); }); |
- 差分送信:
SyncClientは内部で前回の状態と比較し、変化があった場合のみメッセージを送出します。これにより帯域利用が抑えられます。 - エラーハンドリング:
sync.on('error', ...)を登録してネットワーク障害時のリトライロジックを実装すると、ユーザー体験が向上します。
Quest 3 実機デバッグ手順
Meta Quest 3 で動作確認を行う際は ADB と Chrome の Remote Debugging を組み合わせると効率的です。以下ではセットアップからログ取得までの流れをステップ別に解説します。
ADB 接続設定
| 手順 | 内容 |
|---|---|
| 1️⃣ 開発者モード有効化 | Meta Developer Portal(https://developer.oculus.com/)でデバイスを開発者として登録し、Developer Mode をオンにします。 |
| 2️⃣ デバイス側設定 | Quest 3 の 設定 → システム → 開発者 メニューから USB デバッグ と ADB ワイヤレスデバッグ を有効化します。 |
| 3️⃣ PC に Platform‑Tools インストール | https://developer.android.com/studio/releases/platform-tools から platform-tools をダウンロードし、パスを通すか展開ディレクトリで実行します。 |
| 4️⃣ 接続確認 | USB または Wi‑Fi 経由でデバイスが認識されているか確認します。 |
|
1 2 |
adb devices # 表示例: 192.168.1.10:5555 device |
接続できたら、ビルド成果物(dist/app.bundle.js 等)をデバイス内の任意ディレクトリへ転送します。
|
1 2 |
adb push dist/app.bundle.js /sdcard/Android/data/com.example.figminxr/files/ |
Chrome Remote Debugging とログ取得
- Chrome でデバイスを検出
-
chrome://inspect/#devicesにアクセスし、Discover USB devices を有効化。Quest 3 が一覧に表示されたら Inspect ボタンをクリックします。 -
コンソール・ネットワークの確認
-
開いた DevTools で Console タブを開き、
console.log出力や例外スタックトレースをリアルタイムに確認できます。 -
ADB Logcat による詳細ログ取得
- SDK が出すタグ(例:
FigminXR,Unity)でフィルタリングすると必要な情報だけが抽出でき、ファイルへ保存も簡単です。
|
1 2 |
adb logcat -s FigminXR:V Unity:V *:S > quest3.log |
FigminXR:Vは Verbose レベルのログ全てを取得し、*:Sで他のタグはサイレントにします。- 取得した
quest3.logをテキストエディタや VS Code の検索機能で解析すると、フレームレート低下や例外発生箇所が特定しやすくなります。
記事のまとめ
| 項目 | 主なポイント |
|---|---|
| Node.js v22 の Type Stripping | 実験的ローダー --loader=tsx が必要。.tsx は同様にローダーで実行可能。 |
| Figmin XR SDK | npm 1 行で取得、公式推奨の tsconfig.json と ESM 設定で即利用開始。 |
| SpatialRecognition API | 型安全なイベントハンドラと行列ベース座標変換でデバイス依存性を吸収。 |
| GLTF/GLB 最適化 | @gltf-transform/cli の正しいオプション例(--draco.compressionLevel=10)で自動圧縮・テクスチャ変換。 |
| リアルタイム協働 | ws と Figmin XR Sync API による型安全ブロードキャスト実装例を提示。 |
| Quest 3 デバッグ | ADB 設定 → Chrome Remote Debugging → adb logcat のフローで実機テストが高速化。 |
上記手順とコードスニペットをプロジェクトに取り込めば、2026 年版 Figmin XR 開発環境の構築・最適化・マルチユーザー同期まで一通りカバーできます。最新情報は公式 GitHub(https://github.com/figmin/xr-sdk)や Discord コミュニティで随時確認してください。