第 2 篇:搭建第一个 Three.js 项目

第 2 篇:搭建第一个 Three.js 项目

本文是"使用 Three.js 构建转炉数字孪生系统"系列的第 2 篇。

上一篇介绍了 Three.js 在数字孪生系统中的位置和职责边界。本文将真正创建第一个可运行的 Three.js 工程。

本文将使用以下技术组合:

text 复制代码
Node.js
  ↓
npm
  ↓
Vite
  ↓
Three.js
  ↓
浏览器

完成本文后,我们将得到一个具备以下能力的基础工程:

  • 使用 npm 管理 Three.js;
  • 使用 Vite 启动本地开发服务器;
  • 使用 ES Module 导入 Three.js;
  • 创建场景、相机和渲染器;
  • 在浏览器中显示并旋转一个立方体;
  • 使用浏览器开发者工具排查问题;
  • 理解常见安装错误及其处理方法。

一、为什么使用 npm 和 Vite 搭建 Three.js 项目

Three.js 可以通过多种方式运行。

一种方式是在 HTML 中直接引用 CDN 文件,并通过导入映射告诉浏览器 threethree/addons/ 对应哪个地址。

另一种方式是通过 npm 安装 Three.js,再使用 Vite 等构建工具管理开发环境。

对于临时演示,CDN 方式比较方便;但对于转炉数字孪生这类正式工程,更推荐使用 npm 和构建工具。

原因包括:

  • 可以明确记录 Three.js 的版本;
  • 可以统一管理其他依赖;
  • 可以使用标准 ES Module 导入语法;
  • 可以拆分多个 JavaScript 文件;
  • 可以使用开发服务器和热更新;
  • 可以正确处理模型、纹理和静态资源;
  • 可以构建经过压缩和优化的生产版本;
  • 团队成员可以通过 package.json 恢复相同的依赖环境。

Three.js 官方安装说明也将"npm 加构建工具"列为大多数用户的推荐方式。

本文使用 Vite,是因为它配置简单、启动速度快,并且适合现代前端工程。


二、Node.js 是什么

Node.js 是一个 JavaScript 运行环境。

我们平时在浏览器中运行 JavaScript,而 Node.js 允许 JavaScript 在浏览器之外运行,例如执行:

  • 命令行工具;
  • 构建工具;
  • 开发服务器;
  • 自动化脚本;
  • 后端程序;
  • 包管理相关命令。

在本文中,Node.js 并不负责渲染 Three.js 场景。

真正的 Three.js 画面仍然运行在浏览器中。

Node.js 在这个项目中主要负责:

text 复制代码
运行 npm
运行 Vite
安装项目依赖
启动开发服务器
执行生产构建

可以理解为:

Node.js 为前端工程提供开发工具运行环境,浏览器负责运行最终的 Three.js 页面。


三、npm 是什么

npm 是 Node.js 生态中常用的包管理工具。

安装 Node.js 时,通常会同时安装 npm。

npm 可以帮助我们:

  • 创建和读取 package.json
  • 安装 Three.js;
  • 安装 Vite;
  • 记录依赖版本;
  • 下载依赖需要的其他依赖;
  • 执行 package.json 中定义的脚本;
  • 根据 package-lock.json 恢复较一致的安装结果。

例如:

bash 复制代码
npm install three

这条命令的含义是:

从 npm 软件包仓库下载 Three.js,并把它安装为当前项目的依赖。

安装完成后,项目中会出现或更新以下内容:

text 复制代码
package.json
package-lock.json
node_modules/

它们分别具有不同作用。

1. package.json

package.json 是项目说明文件,记录:

  • 项目名称;
  • 项目版本;
  • npm 脚本;
  • 正式依赖;
  • 开发依赖;
  • 其他工程配置。

2. package-lock.json

package-lock.json 记录更具体的依赖解析结果。

它可以帮助不同开发者和不同环境安装较一致的依赖版本。

正式项目通常应该把 package.jsonpackage-lock.json 一起提交到 Git。

3. node_modules

node_modules 保存实际下载的依赖代码。

它通常体积较大,可以根据 package.jsonpackage-lock.json 重新安装,因此一般不提交到 Git,也不直接上传到网站服务器。


四、Vite 是什么

Vite 是现代前端开发工具。

在本教程中,它主要负责:

  • 创建基础项目结构;
  • 启动本地开发服务器;
  • 解析 import 语句;
  • 查找 node_modules 中的 Three.js;
  • 在修改代码后自动刷新页面;
  • 处理静态资源;
  • 构建生产版本。

当我们在代码中编写:

javascript 复制代码
import * as THREE from "three";

浏览器本身并不知道 npm 软件包 three 位于哪里。

Vite 会在开发和构建过程中解析这个导入,并从当前项目的 node_modules 中找到 Three.js。

这使我们不需要在 HTML 中手动维护 CDN 地址和导入映射。


五、安装 Node.js

1. 推荐选择 LTS 版本

Node.js 通常同时提供:

  • Current:包含较新功能;
  • LTS:长期支持版本,更适合学习和正式项目。

对于初学者和数字孪生工程,建议选择仍处于支持期的 LTS 版本。

截至 2026 年 7 月,Node.js 24 和 Node.js 22 都处于 LTS 状态。新项目可以优先选择 Node.js 24 LTS。

当前 Vite 官方文档要求 Node.js 至少满足以下版本范围之一:

text 复制代码
Node.js 20.19+
Node.js 22.12+

但 Node.js 20 已在 2026 年进入停止支持状态,因此不建议为新项目专门安装 Node.js 20。

更直接的建议是:

text 复制代码
优先:Node.js 24 LTS
可用:Node.js 22 LTS,且版本不低于 22.12

随着时间推移,具体版本要求可能变化。遇到 Vite 的版本提示时,应以当时的 Vite 官方文档为准。


2. 使用版本管理器安装

npm 官方文档推荐使用 Node.js 版本管理器,因为版本管理器可以:

  • 安装多个 Node.js 版本;
  • 快速切换版本;
  • 降低全局安装权限问题;
  • 避免不同项目之间的版本冲突。

常见选择包括:

text 复制代码
macOS / Linux:nvm
Windows:nvm-windows
跨平台方案:fnm、Volta 等

需要注意:

nvmnvm-windows 不是同一个项目,安装命令和使用方式也不完全相同。

不熟悉版本管理器时,也可以从 Node.js 官方网站下载 LTS 安装程序。


3. 检查安装结果

安装完成后,关闭并重新打开终端,然后执行:

bash 复制代码
node -v
npm -v

正常情况下会看到类似输出:

text 复制代码
v24.x.x
11.x.x

具体小版本号不需要和示例完全一致。

只要:

  • node -v 能输出版本;
  • npm -v 能输出版本;
  • Node.js 版本满足 Vite 要求;

就可以继续。


六、选择终端和代码编辑器

本文中的命令需要在终端中执行。

常见终端包括:

Windows

  • Windows Terminal;
  • PowerShell;
  • 命令提示符;
  • VS Code 集成终端;
  • WSL 终端。

macOS

  • Terminal;
  • iTerm2;
  • VS Code 集成终端。

Linux

  • 系统终端;
  • VS Code 集成终端。

代码编辑器推荐使用 Visual Studio Code,但 Three.js 并不依赖某个特定编辑器。

在 VS Code 中可以通过菜单打开终端:

text 复制代码
终端 → 新建终端

执行命令前,应先确认终端当前位于准备存放项目的父目录。


七、创建 Vite 项目

本文创建一个名为 threejs-converter-twin 的项目。

在终端中执行:

bash 复制代码
npm create vite@latest threejs-converter-twin -- --template vanilla

各部分含义如下:

text 复制代码
npm create vite@latest

表示使用最新的 Vite 项目创建工具。

text 复制代码
threejs-converter-twin

表示项目文件夹名称。

text 复制代码
-- --template vanilla

表示使用原生 JavaScript 模板,不使用 Vue、React 或其他框架。

创建完成后进入项目目录:

bash 复制代码
cd threejs-converter-twin

安装模板中声明的依赖:

bash 复制代码
npm install

此时,Vite 基础工程已经创建完成。


八、安装 Three.js

确保终端当前位于项目根目录,然后执行:

bash 复制代码
npm install three

安装完成后,可以查看 package.json

其中应出现类似内容:

json 复制代码
{
  "dependencies": {
    "three": "^0.xxx.x"
  }
}

这里的版本号会随着 Three.js 发布新版本而变化,不需要与本文示例完全相同。

可以通过下面的命令检查当前项目实际安装的版本:

bash 复制代码
npm list three

也可以查看 node_modules/three/package.json


九、理解项目目录

执行创建和安装命令后,项目结构大致如下:

text 复制代码
threejs-converter-twin/
├─ node_modules/
├─ public/
├─ src/
│  ├─ counter.js
│  ├─ javascript.svg
│  ├─ main.js
│  └─ style.css
├─ .gitignore
├─ index.html
├─ package-lock.json
└─ package.json

Vite 默认模板中包含一些演示文件,我们可以删除不需要的内容。

整理后的基础目录可以是:

text 复制代码
threejs-converter-twin/
├─ node_modules/
├─ public/
│  ├─ models/
│  ├─ textures/
│  └─ images/
├─ src/
│  ├─ main.js
│  └─ style.css
├─ .gitignore
├─ index.html
├─ package-lock.json
└─ package.json

各目录的作用如下。

1. public

public 用于存放不需要经过 Vite 转换、希望按原文件形式提供的静态资源,例如:

text 复制代码
public/models/converter.glb
public/textures/steel.jpg
public/images/logo.png

它们在代码中的访问路径通常从网站根目录开始:

javascript 复制代码
const modelUrl = "/models/converter.glb";

路径中不需要写 public

错误写法:

javascript 复制代码
const modelUrl = "/public/models/converter.glb";

正确写法:

javascript 复制代码
const modelUrl = "/models/converter.glb";

2. src

src 用于存放源代码。

后续项目中可以继续扩展:

text 复制代码
src/
├─ main.js
├─ style.css
├─ three/
├─ equipment/
├─ effects/
├─ interaction/
└─ data/

3. index.html

index.html 是页面入口。

Vite 会以它为起点加载项目。

4. main.js

main.js 是本文的 JavaScript 入口文件。

Three.js 场景初始化代码将从这里开始执行。


十、修改 index.html

打开项目根目录中的 index.html,替换为下面的内容:

html 复制代码
<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0"
    />
    <title>Three.js 转炉数字孪生教程</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

重点是:

html 复制代码
<script type="module" src="/src/main.js"></script>

type="module" 表示这个脚本使用 ES Module。

因此,main.js 中可以使用:

javascript 复制代码
import
export

十一、创建样式文件

打开 src/style.css,替换为:

css 复制代码
* {
  box-sizing: border-box;
}

html,
body,
#app {
  width: 100%;
  height: 100%;
  margin: 0;
  overflow: hidden;
}

body {
  font-family:
    Inter, "Microsoft YaHei", Arial, sans-serif;
  background: #111827;
}

canvas {
  display: block;
}

这里最重要的是:

css 复制代码
html,
body,
#app {
  width: 100%;
  height: 100%;
  margin: 0;
}

它确保 Three.js 画布可以占满浏览器窗口。

canvas { display: block; } 可以避免画布作为行内元素时产生底部空隙。


十二、创建 Three.js 入口文件

打开 src/main.js,删除原有内容,然后写入:

javascript 复制代码
import * as THREE from "three";
import "./style.css";

const app = document.querySelector("#app");

if (!app) {
  throw new Error("未找到 #app 容器");
}

// 1. 创建场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x111827);

// 2. 创建相机
const camera = new THREE.PerspectiveCamera(
  60,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);

camera.position.set(3, 2, 5);
camera.lookAt(0, 0, 0);

// 3. 创建渲染器
const renderer = new THREE.WebGLRenderer({
  antialias: true
});

renderer.setPixelRatio(
  Math.min(window.devicePixelRatio, 2)
);

renderer.setSize(
  window.innerWidth,
  window.innerHeight
);

app.appendChild(renderer.domElement);

// 4. 创建立方体
const geometry = new THREE.BoxGeometry(1.5, 1.5, 1.5);

const material = new THREE.MeshStandardMaterial({
  color: 0xf97316,
  roughness: 0.45,
  metalness: 0.15
});

const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// 5. 添加灯光
const ambientLight = new THREE.AmbientLight(
  0xffffff,
  1.2
);

scene.add(ambientLight);

const directionalLight = new THREE.DirectionalLight(
  0xffffff,
  3
);

directionalLight.position.set(4, 6, 3);
scene.add(directionalLight);

// 6. 添加网格辅助线
const gridHelper = new THREE.GridHelper(
  10,
  10,
  0x4b5563,
  0x374151
);

gridHelper.position.y = -1.25;
scene.add(gridHelper);

// 7. 处理窗口尺寸变化
function handleResize() {
  camera.aspect =
    window.innerWidth / window.innerHeight;

  camera.updateProjectionMatrix();

  renderer.setSize(
    window.innerWidth,
    window.innerHeight
  );

  renderer.setPixelRatio(
    Math.min(window.devicePixelRatio, 2)
  );
}

window.addEventListener("resize", handleResize);

// 8. 创建动画循环
function animate() {
  cube.rotation.x += 0.005;
  cube.rotation.y += 0.01;

  renderer.render(scene, camera);
}

renderer.setAnimationLoop(animate);

保存文件后,Vite 会自动更新浏览器页面。

如果代码运行正常,可以看到:

  • 深色背景;
  • 一个橙色立方体;
  • 地面网格;
  • 立方体持续旋转。

十三、逐步理解入口代码

1. 导入 Three.js

javascript 复制代码
import * as THREE from "three";

表示从 three 软件包中导入全部公开内容,并统一放到 THREE 对象中。

之后可以使用:

javascript 复制代码
THREE.Scene
THREE.PerspectiveCamera
THREE.WebGLRenderer
THREE.Mesh

Vite 会从 node_modules 中找到这个软件包。


2. 创建场景

javascript 复制代码
const scene = new THREE.Scene();

场景是 Three.js 对象的容器。

模型、灯光和辅助工具都需要加入场景。


3. 创建相机

javascript 复制代码
const camera = new THREE.PerspectiveCamera(
  60,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);

四个参数分别表示:

text 复制代码
视野角度
宽高比
近裁剪面
远裁剪面

相机需要离开原点,否则可能位于立方体内部。

javascript 复制代码
camera.position.set(3, 2, 5);

4. 创建渲染器

javascript 复制代码
const renderer = new THREE.WebGLRenderer({
  antialias: true
});

antialias: true 用于开启抗锯齿,使物体边缘更平滑。

设置尺寸后:

javascript 复制代码
renderer.setSize(
  window.innerWidth,
  window.innerHeight
);

再把渲染器创建的 Canvas 加入网页:

javascript 复制代码
app.appendChild(renderer.domElement);

5. 创建网格对象

Three.js 中常见的可见网格对象由两部分组成:

text 复制代码
Geometry:物体的形状
Material:物体表面的显示方式

最后组合为:

javascript 复制代码
const cube = new THREE.Mesh(
  geometry,
  material
);

6. 添加灯光

本文使用的是 MeshStandardMaterial,它需要灯光才能看清。

如果忘记添加灯光,立方体可能显示为黑色。

为了方便入门,本文同时添加:

text 复制代码
AmbientLight
DirectionalLight

7. 创建动画循环

javascript 复制代码
function animate() {
  cube.rotation.x += 0.005;
  cube.rotation.y += 0.01;

  renderer.render(scene, camera);
}

renderer.setAnimationLoop(animate);

动画循环会不断:

  1. 修改立方体角度;
  2. 根据当前场景和相机重新渲染画面。

后续转炉倾动、氧枪升降、火焰变化和实时数据同步,都会在渲染循环或独立更新模块中完成。


十四、启动开发服务器

在项目根目录执行:

bash 复制代码
npm run dev

终端通常会显示类似内容:

text 复制代码
VITE ready

Local: http://localhost:5173/

按住 Ctrl 并点击地址,或者在浏览器中手动打开它。

如果 5173 端口已被占用,Vite 通常会自动选择其他端口,例如:

text 复制代码
http://localhost:5174/

因此应以终端实际输出的地址为准。


十五、package.json 中的脚本

打开 package.json,通常可以看到:

json 复制代码
{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  }
}

这三个脚本分别用于不同阶段。

开发

bash 复制代码
npm run dev

启动开发服务器,并支持代码热更新。

构建

bash 复制代码
npm run build

生成生产环境文件。

构建结果默认位于:

text 复制代码
dist/

预览构建结果

bash 复制代码
npm run preview

在本地启动一个服务器,预览 dist 中的生产构建结果。

需要注意:

npm run preview 用于本地验证构建结果,不等于正式生产服务器。


十六、为什么不能直接双击 index.html

有些初学者会直接双击 index.html,让浏览器通过类似地址打开:

text 复制代码
file:///D:/project/index.html

这并不是推荐运行方式。

原因包括:

  • ES Module 可能受到浏览器安全策略限制;
  • 模型和纹理请求可能遇到跨域问题;
  • npm 软件包导入无法按工程方式解析;
  • 部分浏览器 API 在 file:// 下行为不同;
  • 相对路径问题更加难以排查。

正确做法是:

bash 复制代码
npm run dev

然后通过:

text 复制代码
http://localhost:5173/

访问项目。


十七、浏览器开发者工具

浏览器开发者工具是排查 Three.js 问题最重要的工具之一。

在 Chrome 或 Edge 中可以使用:

text 复制代码
F12

或者:

text 复制代码
Ctrl + Shift + I

macOS 通常使用:

text 复制代码
Command + Option + I

1. Console:查看 JavaScript 错误

Console 是首先应该检查的面板。

常见错误包括:

text 复制代码
Failed to resolve import "three"
Cannot find package "three"
THREE is not defined
Uncaught TypeError
WebGL context lost

看到空白页面时,不要立即反复修改代码。

第一步应当是打开 Console,阅读第一条红色错误信息。

错误堆栈中的文件名和行号通常可以直接定位问题:

text 复制代码
main.js:24

2. Network:检查资源是否成功加载

Network 面板可以查看:

  • JavaScript 文件;
  • 三维模型;
  • 纹理;
  • JSON 数据;
  • WebSocket;
  • API 请求。

当模型没有显示时,应检查是否存在:

text 复制代码
404 Not Found
500 Internal Server Error
CORS error

例如,模型放在:

text 复制代码
public/models/converter.glb

它的访问地址应当是:

text 复制代码
/models/converter.glb

在 Network 中找到对应请求,可以确认浏览器是否成功获取文件。


3. Sources:设置断点

Sources 面板可以:

  • 查看浏览器实际加载的源码;
  • 在指定行设置断点;
  • 单步执行代码;
  • 查看当前变量;
  • 检查函数调用过程。

例如,可以在模型加载完成回调中设置断点,确认:

  • 回调是否被执行;
  • 模型对象是否存在;
  • 节点名称是否正确;
  • 数据值是否符合预期。

4. Performance:分析卡顿

Performance 面板可以记录页面运行过程,并分析:

  • JavaScript 执行时间;
  • 页面帧率;
  • 长任务;
  • 内存分配;
  • 渲染和绘制耗时。

数字孪生场景出现明显卡顿时,不能只凭感觉判断。

应当通过性能记录确认问题主要来自:

text 复制代码
JavaScript
Three.js 渲染
模型复杂度
大量 Draw Call
纹理上传
频繁创建对象
页面其他组件

5. 检查 Three.js 渲染统计

Three.js 的渲染器提供了基础统计信息:

javascript 复制代码
console.log(renderer.info);

常见字段包括:

text 复制代码
renderer.info.render.calls
renderer.info.render.triangles
renderer.info.memory.geometries
renderer.info.memory.textures

调试时可以临时输出:

javascript 复制代码
setInterval(() => {
  console.log({
    calls: renderer.info.render.calls,
    triangles: renderer.info.render.triangles,
    geometries: renderer.info.memory.geometries,
    textures: renderer.info.memory.textures
  });
}, 2000);

不要在正式项目中长期频繁输出大量日志,否则日志本身也会影响调试体验。


十八、常见安装错误及处理方式

错误一:node 不是内部或外部命令

Windows 中可能看到:

text 复制代码
'node' 不是内部或外部命令

macOS 或 Linux 中可能看到:

text 复制代码
command not found: node

可能原因:

  • Node.js 没有安装;
  • Node.js 安装失败;
  • PATH 环境变量没有更新;
  • 安装后终端没有重新打开;
  • 当前终端使用了另一套环境。

处理步骤:

bash 复制代码
node -v
npm -v

如果都无法执行:

  1. 确认 Node.js 已安装;
  2. 关闭并重新打开终端;
  3. 重新打开 VS Code;
  4. 检查 PATH;
  5. 使用版本管理器重新安装 LTS 版本。

错误二:npm 不是内部或外部命令

如果 node -v 正常,但 npm -v 失败,可能是 npm 安装不完整或 PATH 配置异常。

可以先检查命令位置。

Windows:

powershell 复制代码
where node
where npm

macOS、Linux 或 WSL:

bash 复制代码
which node
which npm

正常情况下,Node.js 和 npm 应来自同一套安装环境。

不要让一个命令来自 Windows,另一个命令来自 WSL 或其他 Node.js 安装目录。


错误三:Vite 提示 Node.js 版本过低

可能看到类似信息:

text 复制代码
Vite requires Node.js version 20.19+ or 22.12+

处理方式是升级 Node.js。

不建议通过修改 Vite 源码、忽略版本检查或强行降级部分依赖来绕过。

更合理的处理方式:

  1. 安装当前受支持的 Node.js LTS;
  2. 关闭并重新打开终端;
  3. 执行 node -v 确认版本;
  4. 删除旧依赖并重新安装。

macOS、Linux 或 WSL:

bash 复制代码
rm -rf node_modules package-lock.json
npm install

Windows PowerShell:

powershell 复制代码
Remove-Item -Recurse -Force node_modules
Remove-Item -Force package-lock.json
npm install

只有在升级 Node.js 后旧依赖确实产生兼容问题时,才需要删除锁文件。一般情况下,不应无理由删除 package-lock.json


错误四:PowerShell 禁止运行 npm.ps1

Windows PowerShell 可能提示:

text 复制代码
npm.ps1 cannot be loaded because running scripts is disabled

可以选择以下方法之一。

方法一:使用命令提示符

在 Windows Terminal 中切换到 Command Prompt,然后执行 npm 命令。

方法二:直接执行 npm.cmd

powershell 复制代码
npm.cmd -v
npm.cmd install

方法三:调整当前用户的执行策略

powershell 复制代码
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned

执行前应理解该设置的作用,并只修改当前用户范围,不要随意降低整个系统的安全策略。


错误五:npm install 长时间没有响应

可能原因包括:

  • 网络连接不稳定;
  • npm 仓库访问缓慢;
  • 代理配置错误;
  • DNS 问题;
  • 企业网络拦截;
  • 安全软件扫描大量小文件;
  • 项目位于性能较差的跨系统挂载目录;
  • 安装脚本正在执行,但终端没有明显输出。

可以依次检查:

bash 复制代码
npm ping
npm config get registry
npm install --verbose
npm cache verify

查看代理配置:

bash 复制代码
npm config get proxy
npm config get https-proxy

不再使用代理时,可以删除错误配置:

bash 复制代码
npm config delete proxy
npm config delete https-proxy

不要把下面的命令当成所有问题的第一解决方案:

bash 复制代码
npm cache clean --force

强制清理缓存通常不是必要步骤,优先使用:

bash 复制代码
npm cache verify

错误六:EACCES 或权限不足

macOS 或 Linux 中,全局安装包时可能看到:

text 复制代码
EACCES: permission denied

npm 官方更推荐使用 Node.js 版本管理器解决此类权限问题。

不建议长期使用:

bash 复制代码
sudo npm install -g ...

对于本文项目,也没有必要全局安装 Vite。

正确方式是把 Vite安装在项目中,并通过 npm 脚本运行:

bash 复制代码
npm run dev

或者:

bash 复制代码
npx vite

错误七:Cannot find package 'three'

可能看到:

text 复制代码
Cannot find package 'three'

或:

text 复制代码
Failed to resolve import "three"

检查以下内容:

  1. 当前终端是否位于项目根目录;
  2. 项目根目录是否存在 package.json
  3. 是否执行过 npm install three
  4. package.json 是否包含 three
  5. node_modules/three 是否存在。

重新安装:

bash 复制代码
npm install three

检查:

bash 复制代码
npm list three

错误八:浏览器页面完全空白

空白页面不一定意味着 Three.js 没有运行。

常见原因包括:

  • JavaScript 已经报错;
  • 相机没有对准物体;
  • 相机位于物体内部;
  • 物体在裁剪范围之外;
  • 使用受光材质但没有灯光;
  • 物体颜色和背景颜色相同;
  • Canvas 宽度或高度为 0;
  • 没有执行 renderer.render()
  • HTML 没有加载正确的入口文件。

排查顺序:

  1. 打开 Console;
  2. 查看第一条红色错误;
  3. 确认 main.js 被加载;
  4. 确认 Canvas 已插入页面;
  5. 给场景设置明显背景色;
  6. 使用 MeshBasicMaterial 临时排除灯光问题;
  7. 添加 AxesHelperGridHelper
  8. 检查相机位置。

例如:

javascript 复制代码
scene.add(new THREE.AxesHelper(5));

错误九:模型或纹理出现 404

例如模型存放位置是:

text 复制代码
public/models/converter.glb

正确访问路径是:

javascript 复制代码
"/models/converter.glb"

而不是:

javascript 复制代码
"/public/models/converter.glb"

应通过浏览器 Network 面板确认请求地址和响应状态。

文件名大小写也需要注意。

Windows 文件系统可能对大小写不敏感,但 Linux 服务器通常区分:

text 复制代码
Converter.glb
converter.glb

这两个名称在 Linux 中不是同一个文件。


错误十:端口被占用

默认端口被占用时,Vite通常会自动选择新端口。

也可以手动指定:

bash 复制代码
npm run dev -- --port 5174

如果要求端口被占用时直接失败:

bash 复制代码
npm run dev -- --port 5173 --strictPort

错误十一:导入 OrbitControls 或 GLTFLoader 失败

Three.js 的控制器、加载器和后处理等功能属于 addons,需要单独导入。

正确写法:

javascript 复制代码
import * as THREE from "three";

import {
  OrbitControls
} from "three/addons/controls/OrbitControls.js";

import {
  GLTFLoader
} from "three/addons/loaders/GLTFLoader.js";

不需要单独执行:

bash 复制代码
npm install OrbitControls
npm install GLTFLoader

这些 addons 已包含在 three 软件包中。

需要特别注意导入路径末尾的:

text 复制代码
.js

错误十二:同时导入多个 Three.js 实例

如果项目同时使用:

  • npm 安装的 Three.js;
  • CDN 中的 Three.js;
  • 不同版本的 addons;
  • 第三方库自带的另一份 Three.js;

可能出现:

text 复制代码
Multiple instances of Three.js being imported

解决原则:

  • 项目中统一通过 npm 导入;
  • 不在 Vite 项目中混用 CDN 导入映射;
  • threethree/addons/ 使用同一软件包版本;
  • 检查第三方依赖是否重复携带 Three.js;
  • 使用 npm ls three 查看依赖树。

十九、Windows 与 WSL 的特别注意事项

使用 WSL 开发时,最常见的问题之一是混用 Windows 和 Linux 环境。

例如:

text 复制代码
node 来自 WSL
npm 来自 Windows
项目位于 Windows 挂载盘
全局工具来自另一套 Node.js

这可能导致:

  • 可选依赖安装错误;
  • 命令入口指向错误;
  • 路径格式冲突;
  • 权限异常;
  • 安装速度极慢;
  • 原生模块平台不匹配。

建议检查:

bash 复制代码
which node
which npm
node -p "process.platform"
node -p "process.arch"
npm config get prefix

在 WSL 中开发时,建议:

  • 在 WSL 内单独安装 Node.js;
  • 不直接复用 Windows 的 Node.js;
  • Node.js、npm 和项目命令来自同一环境;
  • 优先把频繁安装依赖的项目放在 WSL Linux 文件系统中,例如 ~/projects/
  • 避免一会儿用 Windows 终端安装,一会儿用 WSL 安装同一个项目;
  • 切换运行环境后重新删除并安装 node_modules

例如:

bash 复制代码
mkdir -p ~/projects
cd ~/projects
npm create vite@latest threejs-converter-twin -- --template vanilla

二十、创建项目后的第一次自检

完成项目后,可以按照下面的顺序检查。

环境检查

bash 复制代码
node -v
npm -v

目录检查

bash 复制代码
pwd

Windows PowerShell 可以使用:

powershell 复制代码
Get-Location

依赖检查

bash 复制代码
npm list vite
npm list three

启动检查

bash 复制代码
npm run dev

构建检查

bash 复制代码
npm run build

浏览器检查

  • 页面是否正常显示;
  • Console 是否没有红色错误;
  • Network 是否没有意外 404;
  • 修改代码后页面是否自动更新;
  • 调整窗口大小后 Canvas 是否自适应。

二十一、建议保留的最小工程结构

完成本文后,建议把项目整理为:

text 复制代码
threejs-converter-twin/
├─ public/
│  ├─ models/
│  ├─ textures/
│  └─ images/
├─ src/
│  ├─ main.js
│  └─ style.css
├─ .gitignore
├─ index.html
├─ package-lock.json
└─ package.json

不要提交:

text 复制代码
node_modules/
dist/

Vite 模板通常已经在 .gitignore 中忽略这些目录。


二十二、本篇完成后的结果

到这里,我们已经完成:

  • 安装 Node.js 和 npm;
  • 理解 Node.js、npm 与 Vite 的关系;
  • 创建原生 JavaScript Vite 项目;
  • 使用 npm 安装 Three.js;
  • 建立项目目录;
  • 创建 HTML 和 JavaScript 入口;
  • 启动本地开发服务器;
  • 创建第一个 Three.js 场景;
  • 显示一个持续旋转的立方体;
  • 学会使用浏览器开发者工具;
  • 了解常见安装和运行错误。

目前的项目还只是一个 Three.js 最小工程,但它已经具备后续扩展所需的基本条件。

接下来可以逐步加入:

  • 场景;
  • 相机;
  • 灯光;
  • 控制器;
  • 转炉模型;
  • 氧枪模型;
  • 实时数据;
  • 设备状态;
  • 动画系统;
  • 性能监控。

二十三、本文总结

Node.js、npm、Vite 和 Three.js 的关系可以概括为:

text 复制代码
Node.js:运行开发工具
npm:安装和管理依赖
Vite:组织、启动和构建前端项目
Three.js:实现浏览器三维场景
浏览器:执行最终页面并调用 GPU 渲染

对于正式数字孪生工程,推荐采用:

text 复制代码
Node.js LTS
+
npm
+
Vite
+
Three.js

而不是把所有脚本都通过 CDN 临时拼接在一个 HTML 文件中。

项目化安装的核心价值不仅是"能够运行",更是:

  • 依赖可追踪;
  • 版本可控制;
  • 代码可拆分;
  • 问题可调试;
  • 工程可构建;
  • 团队可协作;
  • 后续可扩展。

二十四、下一篇学习内容

下一篇建议进入 Three.js 最核心的运行结构:

第 3 篇:场景、相机、渲染器与动画循环

下一篇将重点介绍:

  • Scene
  • PerspectiveCamera
  • OrthographicCamera
  • WebGLRenderer
  • Canvas;
  • 坐标系;
  • 动画循环;
  • Delta Time;
  • 窗口尺寸自适应;
  • 像素比;
  • Three.js 每一帧到底执行了什么。

参考资料

相关推荐
宁风NF1 小时前
JavaScript:网络请求与前端通信
开发语言·前端·javascript·网络·学习·ecmascript
猫猫不是喵喵.2 小时前
Vue3 中 computed 计算属性与 watch、watchEffect 监听
前端·javascript·vue.js
猫猫不是喵喵.3 小时前
Vue2 的 Vuex 状态管理与 Vue3 的 Pinia 状态管理
前端·javascript·vue.js
看昭奚恤哭3 小时前
Flutter 布局核心思想
开发语言·javascript·flutter
朝阳5814 小时前
Cesium `Camera.flyTo`:“飞过去“
javascript
宁风NF5 小时前
JavaScript:内存、垃圾回收、性能优化
开发语言·前端·javascript·学习·性能优化·es6
午安~婉5 小时前
挑战二:博客预览卡片
前端·javascript·html
夏殇之殁16 小时前
包中创建自定义列表项。 . 使用自定义列表项进行数据绑定 . 将天气预报数据保存到本地内存表,通过LiveBindings进行显示。 ...
服务器·前端·javascript
新中地GIS开发老师18 小时前
WebGIS开发学生作品|低空航天管理与航线规划系统
前端·javascript·webgis·三维gis开发