LoginSignup
11
2

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-02-22

概要

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想定だったため、今回のようなエラーが発生したのでは...?など予想しています。(詳しい人教えてください。)

11
2
1

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
11
2