在 next.js 中加载 GLTF 模型 / 错误:无法加载<url>响应。body.getReader 不是一个函数



如何在next.js中加载模型GLTF模型?

我花了几个小时找这个。什么都不起作用:(


到目前为止我尝试了什么:

  • 使用不同的加载器(useLoader(GLTFLoader,url) / useGLTF(url) and some more
  • 将组件包装在next/dynamic组件中/不要这样做
  • 用react 18安装next解决suspense不支持的相关错误
  • 尝试了此入门模板
  • 使用three-stdlib
  • 尝试在next.config.js中编写自定义加载程序

阅读我能在tis问题上找到的每一期和论坛帖子


我现在得到的错误是:

Server Error
Error: Could not load  <url> response.body.getReader is not a function

有一个组件看起来像这样:

import React from 'react'
import { useGLTF } from '@react-three/drei'
import { Canvas, } from '@react-three/fiber'
import { Suspense } from 'react/cjs/react.production.min';
export default function Spinner({ ...props }) {
const model = useGLTF("http://localhost:3000/spinner.glb")
return (
<Suspense fallback={"loading"}>
<Canvas
camera={{ position: [1, 1, 1] }}
>
<primitive object={model.scene} />
<color attach="background" args={["hotpink"]} />
</Canvas>
</Suspense>
)
}

package.json:

},
"dependencies": {
"@react-three/drei": "^7.27.3",
"@react-three/fiber": "^7.0.21",
"axios": "^0.24.0",
"next": "^12.0.7",
"react": "^18.0.0-beta-24dd07bd2-20211208",
"react-dom": "^18.0.0-beta-24dd07bd2-20211208",
"three": "^0.135.0",
"three-stdlib": "^2.6.1"
},
"devDependencies": {
"eslint": "8.4.1",
"eslint-config-next": "12.0.7",
"file-loader": "^6.2.0"
}
}

节点版本:

16 LTS

用父组件封装Model组件并使用惰性导入可以解决问题,例如

模型组件

import React from 'react'
import { useGLTF } from '@react-three/drei'
export default function Model() {
const model = useGLTF("http://localhost:3000/spinner.glb")
return (
<primitive object={model.scene} />
)
}

使用lazy((导入的场景组件

import { lazy, Suspense } from 'react'
import { Canvas, } from '@react-three/fiber'
const ModelComponent = lazy(() => import("./model"));
export default function Spinner({ ...props }) {
return (
<Suspense fallback={"loading"}>
<Canvas
camera={{ position: [1, 1, 1] }}
>
<ModelComponent />
<color attach="background" args={["hotpink"]} />
</Canvas>
</Suspense>
)
}

这似乎与SSR有关。Next中的TextureLoaders也出现了类似的问题,并经历了类似的困难来修复它,最终通过lazy((导入找到了解决方案。我刚刚在模型负载中尝试过,效果很好。现在无法跟踪此原始线程,但将尝试跟踪并将其添加到此处。

在nextJS中,您不需要使用挂起组件。使用@react three/drei中的useTexture挂钩,而不是使用useLoader加载。

此示例代码加载带有纹理的模型。

import React from "react";
import { useTexture } from "@react-three/drei";
function Box() {
const colorMap = useTexture("/img/robot.png");
return (
<mesh rotation={[90, 0, 20]}>
<boxBufferGeometry attach="geometry" args={[2, 2, 2]} />
<meshNormalMaterial attach="material" />
</mesh>
);
}
export default Box;

在我的案例中起作用的是:

import React from 'react'
import { useGLTF } from '@react-three/drei'
import Spinner from "@/public/spinner.glb"
export default function Model () {
const glb = useGLTF(Spinner.src)
return (
<primitive object={model.scene} />
)
}