この記事はバージョン Spring ’26 において執筆しています。
現在の動作と異なる場合がありますので、ご認識おきください。
Experience Cloud上に3Dカーコンフィギュレーターを実装する際、フロントエンドの描画エンジンとしてThree.jsを採用するのが一般的です。しかし、SalesforceのLWC環境にそのままThree.jsを導入しようとすると、プラットフォーム特有のモジュール仕様、ファイル容量制限、そして厳格なセキュリティポリシーという3つの壁に直面します。
本記事では、連載第2回として、これらの制約を越えて外部の高品質な3Dモデルを安全かつ確実に読み込むためのアーキテクチャと実装手法を解説します。
今回の記事で作成したコンポーネントと.glbファイル(ZIP)をGitHubで公開しています。 ぜひ Clone して、あなたの組織で動かしてみてください。
LWCの仕様制約と外部リソース読み込みの要件
Salesforce環境でThree.jsと外部アセットを扱う場合、以下の仕様制約を前提とした設計が要求されます。
ES Modules(ESM)の非対応と独自ビルド
- 課題: LWCで外部スクリプトを非同期に読み込む
loadScriptAPIは、ESM(import/export構文)をネイティブにサポートしていません。最新のThree.jsやそのアドオン(GLTFLoaderやOrbitControls)はESMで提供されているため、そのまま静的リソースに配置してもロード時に構文エラーとなります。 - 解決策: ローカルのNode.js環境でモジュールバンドラー(Rollup)を使用します。Three.jsのコアエンジンと必要なすべてのアドオンを、ブラウザで即時実行可能なIIFE形式の単一ファイル(
three-bundle.min.js)として統合ビルドし、静的リソースにアップロードします。これにより、ロード順序の複雑化を避け、一度のloadScript呼び出しで全機能へのアクセスが可能になります。
静的リソースの5MB制限と外部ホスティング
- 課題: Salesforceの静的リソースは、単一ファイル(非圧縮状態)で最大5MBという厳格な容量制限があります。高品質な3Dモデル(.glbファイル)は数MB〜数十MBに達することが多く、Salesforce内部でのホスティングが困難です。
- 解決策: 容量制限を回避するため、.glbファイルは外部サーバー(AWS / Xserver等)に配置し、LWCからはその絶対URLを指定して直接パースします。
- 必須となるセキュリティ設定: 外部サーバーと通信を行うため、以下の設定が仕様上必須となります。
- Salesforce側の設定: 「設定」メニューの「信頼済み URL」に、外部サーバーのドメインを登録し、通信ブロックを解除します。
- 外部サーバー側の設定: アセットをホストするサーバーの
.htaccessにAccess-Control-Allow-Origin: *(またはSalesforce組織のドメイン)が正しく出力されるよう設定します。
# glb および .gltf ファイルに対するCORSを許可する
<FilesMatch "\.(glb|gltf)$">
Header set Access-Control-Allow-Origin "*"
</FilesMatch>
# .glbファイルのMIMEタイプを定義する
AddType model/gltf-binary .glb
LWS環境下でのWorker生成制限(CSPエラー)
- 課題: LWS(Lightning Web Security)が有効な環境において、外部サーバーから取得した3Dモデルをパースする際、Three.js内部で使用される
ImageBitmapがblob: Workerを生成しようと試みます。しかし、SalesforceのCSP設定によってはこれがブロックされ、モデルのロードが途中で失敗します。 - 解決策: モデルロードの直前のみ
window.createImageBitmapを一時的にundefinedに上書きし、Three.js側のパーサーを従来のImageオブジェクトによる読み込み処理へと強制的にフォールバックさせます。
実装手順:ローカルビルドとLWCへの組み込み
Node.jsのインストール(準備)
PCにNode.jsがインストールされていない場合は、事前の準備が必要です。
- Node.js公式サイトにアクセスします。
- 「LTS(推奨版)」と記載されているインストーラーをダウンロードし、画面の指示に従ってインストールします。
- インストール完了後、ターミナル(Windowsの場合はコマンドプロンプトやPowerShell、Macの場合はターミナル)を開き、以下のコマンドを入力してバージョンが表示されれば成功です。
# Node.jsのバージョン確認
node -v
# npmのバージョン確認
npm -v
プロジェクトフォルダの作成と初期化
作業用のフォルダを作成し、npmの管理下に入れます。フォルダ作成はコマンドではなくGUIで実施してもOK。
# 作業フォルダを作成し、そのフォルダに移動する
mkdir lwc-threejs-build
cd lwc-threejs-build
# npmプロジェクトとして初期化(package.jsonという管理ファイルが作成される)
npm init -y
Three.jsをダウンロード
Three.js本体と、ビルドを実行するためのRollup本体およびプラグイン(拡張機能)をダウンロードします。
# Three.js本体のインストール
npm install three
# バンドラー(Rollup)とプラグインのインストール
npm install --save-dev rollup @rollup/plugin-node-resolve @rollup/plugin-terser
@rollup/plugin-node-resolve:
npmでインストールしたThree.jsのファイルをRollupが正しく見つけて読み込むためのプラグインです。@rollup/plugin-terser:
最終的な出力ファイルのサイズを削る(圧縮する)ためのプラグインです。
ビルド設定ファイルとエントリーファイルの作成
ソースコードを格納するディレクトリ src と、各種設定を行うための空ファイルをターミナルから作成します。お使いのOSに合わせてコマンドを実行してください。
# ソースコード用ディレクトリの作成(Mac / Windows 共通)
mkdir src
# ==========================================
# 【Mac / Linux / Windows WSL の場合】
# ==========================================
touch src/three-entry.js
touch rollup.config.mjs
# ==========================================
# 【Windows PowerShell の場合】
# ==========================================
New-Item src/three-entry.js
New-Item rollup.config.mjs
この時点で、フォルダ構成は以下のようになっています。
lwc-threejs-build/
├─ node_modules/ # インストールしたパッケージが入るフォルダ(触らない)
├─ package.json # npmの設定ファイル
├─ package-lock.json # パッケージのバージョン固定ファイル(触らない)
├─ rollup.config.mjs # ★新規作成: Rollupの設定ファイル
└─ src/ # ★新規作成: 元となるソースコードを入れるフォルダ
└─ three-entry.js # ★新規作成: 結合の起点となるファイル
VS Codeなどのエディタを使用して、先ほど作成した2つのファイルに以下のコードを記述(ペースト)して保存します。
src/three-entry.js
import * as THREE from 'three';
// 必要な各アドオンを個別にインポートする
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
// ESモジュールの名前空間オブジェクト(THREE)は拡張不可(Object.isExtensible = false)なため、
// スプレッド構文でコピーして新しい拡張可能なオブジェクトを作成する
const THREE_EXTENDED = { ...THREE };
// 各アドオンをプロパティとして追加する
THREE_EXTENDED.GLTFLoader = GLTFLoader;
THREE_EXTENDED.DRACOLoader = DRACOLoader;
THREE_EXTENDED.OrbitControls = OrbitControls;
THREE_EXTENDED.RoomEnvironment = RoomEnvironment;
// LWCのloadScriptで参照できるように、windowオブジェクトへ割り当てる
window.THREE = THREE_EXTENDED;
rollup.config.mjs
import resolve from '@rollup/plugin-node-resolve';
import terser from '@rollup/plugin-terser';
export default {
input: 'src/three-entry.js',
output: {
// 出力先のディレクトリとファイル名
file: 'dist/three-bundle.min.js',
// LWCのloadScriptで読み込まれた瞬間に実行されるIIFE形式を指定
format: 'iife',
name: 'ThreeJSBundle'
},
plugins: [
resolve(),
terser() // 出力ファイルの最小化(圧縮)
]
};
package.json へのビルドコマンド追記と実行
エディタで package.json を開き、"scripts" セクションに、Rollupを実行するためのコマンド "build": "rollup -c" を追記して保存します。
{
"scripts": {
"build": "rollup -c"
}
}
ターミナルに戻り、以下のコマンドを実行してビルドを開始します。
npm run build
処理が成功すると、自動的に dist ディレクトリが作成され、その中に three-bundle.min.js が生成されます。このファイルはThree.jsのコアエンジンとGLTFLoaderが統合され、ESMに依存しない形式で圧縮されています。
LWCからの読み込み実装例
生成された three-bundle.min.js を、Salesforce組織の静的リソースにアップロードします(例としてリソース名を threejsBundle とします)。
これにより、LWC側では単一ファイルの非同期読み込みのみでThree.jsを初期化することが可能になります。
import { LightningElement } from 'lwc';
import { loadScript } from 'lightning/platformResourceLoader';
// Rollupで独自ビルドしたThree.js統合バンドル
import THREEJS_BUNDLE from '@salesforce/resourceUrl/threejsBundle';
// 外部サーバーにホストしたモデルの絶対URL
const CAR_MODEL_URL = 'https://dxforce.site/assets/3d_model/Mclaren_final_eevee.glb';
export default class CarConfigurator extends LightningElement {
// (...中略: Three.jsの初期化処理など...)
loadCarModel() {
// LWS環境での blob: Worker 生成エラーを回避するため、ImageBitmapの利用を一時的に無効化
const originalCreateImageBitmap = window.createImageBitmap;
window.createImageBitmap = undefined;
const gltfLoader = new window.THREE.GLTFLoader();
// 外部サーバーの絶対URLを直接指定してロード
gltfLoader.load(
CAR_MODEL_URL,
(gltf) => {
// ロード成功時に環境を元に戻す
window.createImageBitmap = originalCreateImageBitmap;
this.carModelGroup = gltf.scene;
this.scene.add(this.carModelGroup);
// (...中略: カラー初期設定やUI状態の更新処理...)
},
undefined,
(error) => {
// エラー時も環境を元に戻す
window.createImageBitmap = originalCreateImageBitmap;
console.error('外部モデルの読み込みに失敗しました。CORS設定を確認してください。', error);
}
);
}
}
この構成により、Salesforceプラットフォームのファイル容量制限に縛られることなく、外部CDNや自社サーバーの大容量アセットをExperience Cloud上で柔軟に活用することが可能になります。
参考URL
Use Third-Party JavaScript Libraries (Salesforce Developers)
LWC でのサードパーティ Web コンポーネントの使用 (Beta)
Manage Trusted URLs
Installation | Three.js
ResizeObserver API (MDN Web Docs)






読者の声