LoginSignup
2

More than 1 year has passed since last update.

posted at

updated at

three.jsのGLTFLoader.jsのimportに失敗したときの解決備忘録

概要

2022年2月22日時点の現象

こちらのDownloadからZipダウンロードしたファイル群を下のように展開

ディレクトリ構造

root
└ index.html
└ index.js
└ three.js-master/three.js-master
  └ build/three.module.js
  └ examples/jsm/loaders/GLTFLoader.js

GLTFLoader.jsをimport

index.js
import * as THREE from './three.js-master/three.js-master/build/three.module.js'
import {GLTFLoader} from './three.js-master/three.js-master/examples/jsm/loaders/GLTFLoader.js'

サーバー立ち上げ

npm start —force

localhost:8080を確認するもエラー

image.png

Uncaught TypeError: Failed to resolve module specifier "three". Relative references must start with either "/", "./", or "../"

解決法

GLTFLoader.jsの64行目付近の from文

元々はこちら

GLTFLoader.js
//中略
	VectorKeyframeTrack,
	sRGBEncoding
} from 'three';
//中略

from 'three'; の部分をfrom '../../../build/three.module.js';に変更

GLTFLoader.js
//中略
	VectorKeyframeTrack,
	sRGBEncoding
} from '../../../build/three.module.js';
//中略

これで解決しました。


追記 (おそらくこちらの方が正着?)

@o_obさんからTwitterでコメントをいただきました。(ありがとうございます!)

参考にした結果以下の書き方でも解決しました。

GLTFLoader.jsは元のまま

GLTFLoader.js
//中略
	VectorKeyframeTrack,
	sRGBEncoding
} from 'three';
//中略

エラー時のhtml

index.html

<html lang="ja">
<head>
  <meta charset="utf-8"/>
  <meta http-equiv="X-UA-Compatible">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>3D Model Loader</title>
</head>
<body>
  <canvas class="webgl" id="myCanvas"></canvas>
  <script src="index.js" type="module"></script>
</body>
</html>

修正後のhtml

index.html

<html lang="ja">
<head>
  <meta charset="utf-8"/>
  <meta http-equiv="X-UA-Compatible">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>3D Model Loader</title>
  <!-- 追加 -->
	<script type="importmap">
    {
      "imports": {
        "three": "./three.js-master/three.js-master/build/three.module.js"
      }
    }
  </script>
<!-- ここまで -->
</head>
<body>
  <canvas class="webgl" id="myCanvas"></canvas>
  <script src="index.js" type="module"></script>
</body>
</html>

importMapとは

気になったので調べました。

「JavaScript の実際のファイル名」と「そのファイルを import するときに指定する名前」を切り離すことができます(2つの対応情報はJSON形式で用意しておきます)。
これにより、ファイル名が後から変わっても(ファイル名にバージョン番号が含まれている場合など)、一度記述した import 文を変更する必要はなくなります。(JSON形式による対応情報側のみを変えます)
npm のパッケージ名のようなシンプルな名前でインポートできます。
静的インポート、動的インポートのどちらでも使えます。

とのこと。
これにより threeという名まえを使えるようになるということですね。

ちなみに、three.jsのサンプル実装では

webgl_loader_gltf.html
		<!-- Import maps polyfill 古いブラウザーでも動かすためのコード -->
		<!-- Remove this when import maps will be widely supported この1行はimport mapが普及したら削除してよい -->
		<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>

		<script type="importmap">
			{
				"imports": {
					"three": "../build/three.module.js"
				}
			}
		</script>

とありました。こちら確認しておけば...!

補足議論

おそらく、three.js開発者はnode_modulesによるinstall想定だったため、今回のようなエラーが発生したのでは...?など予想しています。(詳しい人教えてください。)

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
What you can do with signing up
2