控制台警告有三份 three.js,拾取全失效
模型能显示,但点击拾取永远不命中;控制台第一条就是“Multiple instances of Three.js being imported”。
现象
控制台重复出现警告,之后所有依赖 instanceof 的判断都失败:
WARNING: Multiple instances of Three.js being imported.
Uncaught TypeError: Cannot read properties of undefined (reading 'isVector3')
at Raycaster.intersectObject (Raycaster.js:312)
拖拽控制器也失灵,因为控制器来自另一份 three,与场景中的对象类型不匹配。
原因
依赖树里出现了多份 three:项目直接依赖 r169,
某个插件依赖 r150,另一个 GIS 组件又带了 r160。
每份都有自己的 Vector3、Mesh 类,
obj.isMesh 这类鸭子类型判断在跨实例时不受影响,
但 instanceof 与基于构造函数的检查会失败。
排查过程
列出依赖树中的所有 three 副本:
npm ls three
# ├── three@0.169.0
# ├─┬ some-plugin@2.3.1
# │ └── three@0.150.1
# └─┬ gis-widget@1.4.0
# └── three@0.160.0
也可以在浏览器里比较两份模块的版本常量:
console.log(THREE.REVISION); // 169
console.log(otherTHREE.REVISION); // 150,说明确实有两份
解决方案
先尝试去重。多数情况下依赖范围是兼容的,提升到同一份即可:
npm dedupe
# 或在 package.json 中加 overrides
{
"overrides": {
"three": "0.169.0"
}
}
插件不兼容新版本时,用构建别名强制所有引用指向同一份:
// webpack.config.js
module.exports = {
resolve: {
alias: {
three: path.resolve(__dirname, 'node_modules/three')
}
}
};
// vite.config.js
export default {
resolve: {
dedupe: ['three']
}
};
编写内部组件库时,把 three 放到 peerDependencies,
不要放进 dependencies,从源头上避免副本:
{
"peerDependencies": {
"three": "^0.169.0"
},
"devDependencies": {
"three": "^0.169.0"
}
}
验证
控制台不再出现 Multiple instances of Three.js。
npm ls three 只剩一条记录。
射线拾取能命中模型,拖拽控制器与场景对象配合正常。
警告不是噪音:这条警告出现时,很多“莫名其妙”的类型错误都由它引起。 看到就先处理副本,再排查业务代码,能省大量时间。
经纬志(2026)。《控制台警告有三份 three.js,拾取全失效》。https://www.jingweizhi.com/cookbook/duplicate-library-instance.html(访问日期 2026-11-03)。