You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js项目模块解析错误求助:Uncaught TypeError: Failed to resolve module specifier 'three'

Three.js项目模块解析错误求助:Uncaught TypeError: Failed to resolve module specifier 'three'

我现在尝试用CDN导入Three.js核心库、几个官方插件以及N8AO,结果遇到了标题里的错误:

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

我是在Chrome浏览器里遇到的这个问题,还没试其他浏览器。开发环境用的是WebStorm,Node.js版本是22.12.0,不过我没有把功能拆分到单独的JS文件,而是全部写在HTML文件里,方便把所有代码放在一个地方。

我猜测问题出在import语句里,所以把完整的项目代码贴出来,说不定能提供更多排查线索:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Three.js Terrain with Grass and N8AO</title>
  <style>
    body { margin: 0; overflow: hidden; }
    canvas { display: block; }
  </style>
</head>
<body>
<script type="module">
  import * as THREE from 'https://unpkg.com/three@0.169.0/build/three.module.js';
  import { OrbitControls } from 'https://unpkg.com/three@0.169.0/examples/jsm/controls/OrbitControls.js';
  import { EffectComposer } from 'https://unpkg.com/three@0.169.0/examples/jsm/postprocessing/EffectComposer.js';
  import { N8AOPass } from "https://unpkg.com/n8ao@latest/dist/N8AO.js";

  // Scene, Camera, Renderer
  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
  camera.position.set(15, 15, 10);

  const renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  document.body.appendChild(renderer.domElement);

  // Controls
  const controls = new OrbitControls(camera, renderer.domElement);
  controls.minPolarAngle = Math.PI / 2.5;
  controls.maxPolarAngle = Math.PI / 2.5;

  // Sky and lighting
  scene.background = new THREE.Color(0xaabbff); // Sky color
  scene.add(new THREE.AmbientLight(0x404040)); // Soft ambient light

  const pointLight = new THREE.PointLight(0xffffff, 1);
  pointLight.position.set(10, 10, 10);
  pointLight.castShadow = true;
  scene.add(pointLight);

  // Terrain
  const width = 100;
  const terrainGeometry = new THREE.PlaneGeometry(width, width, 64, 64);
  terrainGeometry.rotateX(-Math.PI / 2);

  // Generate elevation for terrain
  const simplex = new THREE.SimplexNoise();
  for (let i = 0; i < terrainGeometry.attributes.position.count; i++) {
    const x = terrainGeometry.attributes.position.array[i * 3];
    const z = terrainGeometry.attributes.position.array[i * 3 + 2];
    const y = 2 * simplex.noise2D(x / 10, z / 10) + 3 * simplex.noise2D(x / 15, z / 15);
    terrainGeometry.attributes.position.array[i * 3 + 1] = y;
  }
  terrainGeometry.computeVertexNormals();

  const terrainMaterial = new THREE.MeshStandardMaterial({ color: 0x228b22 });
  const terrain = new THREE.Mesh(terrainGeometry, terrainMaterial);
  terrain.receiveShadow = true;
  scene.add(terrain);

  // Grass
  const grassGroup = new THREE.Group();
  const bladeGeometry = new THREE.PlaneGeometry(0.12, 1, 1, 4).translate(0, 0.5, 0);
  const grassMaterial = new THREE.MeshStandardMaterial({ color: 0x32cd32, side: THREE.DoubleSide });

  for (let i = 0; i < 50000; i++) {
    const blade = new THREE.Mesh(bladeGeometry, grassMaterial);
    blade.position.set(
            Math.random() * width - width / 2,
            0,
            Math.random() * width - width / 2
    );
    blade.rotation.y = Math.random() * Math.PI * 2;
    blade.scale.y = 0.5 + Math.random() * 0.5;
    grassGroup.add(blade);
  }
  scene.add(grassGroup);

  // Post-Processing with N8AOPass
  const composer = new EffectComposer(renderer);
  const n8aoPass = new N8AOPass(scene, camera, window.innerWidth, window.innerHeight);
  composer.addPass(n8aoPass);

  // Adjust N8AOPass Parameters
  n8aoPass.configuration.aoRadius = 5.0; // Set AO radius
  n8aoPass.configuration.distanceFalloff = 1.0; // Distance attenuation
  n8aoPass.configuration.intensity = 3.0; // AO intensity
  n8aoPass.configuration.color = new THREE.Color(0, 0, 0); // AO color
  n8aoPass.configuration.halfRes = false; // Full resolution for better quality

  // Animation loop
  function animate() {
    requestAnimationFrame(animate);

    // Simulate grass swaying in the wind
    grassGroup.children.forEach((blade) => {
      blade.rotation.x = 0.1 * Math.sin(performance.now() / 1000 + blade.position.x);
    });

    composer.render();
  }
  animate();

  // Handle resizing
  window.addEventListener("resize", () => {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
    composer.setSize(window.innerWidth, window.innerHeight);
  });
</script>
</body>
</html>

最后补充下我的环境版本信息:

  • Chrome浏览器版本:131.0.6778.109
  • WebStorm版本:#WS-242.21829.149

备注:内容来源于stack exchange,提问作者Zodiac

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 16:37:56