第 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 文件,并通过导入映射告诉浏览器 three 和 three/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.json 和 package-lock.json 一起提交到 Git。
3. node_modules
node_modules 保存实际下载的依赖代码。
它通常体积较大,可以根据 package.json 和 package-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 等
需要注意:
nvm和nvm-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);
动画循环会不断:
- 修改立方体角度;
- 根据当前场景和相机重新渲染画面。
后续转炉倾动、氧枪升降、火焰变化和实时数据同步,都会在渲染循环或独立更新模块中完成。
十四、启动开发服务器
在项目根目录执行:
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
如果都无法执行:
- 确认 Node.js 已安装;
- 关闭并重新打开终端;
- 重新打开 VS Code;
- 检查 PATH;
- 使用版本管理器重新安装 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 源码、忽略版本检查或强行降级部分依赖来绕过。
更合理的处理方式:
- 安装当前受支持的 Node.js LTS;
- 关闭并重新打开终端;
- 执行
node -v确认版本; - 删除旧依赖并重新安装。
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"
检查以下内容:
- 当前终端是否位于项目根目录;
- 项目根目录是否存在
package.json; - 是否执行过
npm install three; package.json是否包含three;node_modules/three是否存在。
重新安装:
bash
npm install three
检查:
bash
npm list three
错误八:浏览器页面完全空白
空白页面不一定意味着 Three.js 没有运行。
常见原因包括:
- JavaScript 已经报错;
- 相机没有对准物体;
- 相机位于物体内部;
- 物体在裁剪范围之外;
- 使用受光材质但没有灯光;
- 物体颜色和背景颜色相同;
- Canvas 宽度或高度为 0;
- 没有执行
renderer.render(); - HTML 没有加载正确的入口文件。
排查顺序:
- 打开 Console;
- 查看第一条红色错误;
- 确认
main.js被加载; - 确认 Canvas 已插入页面;
- 给场景设置明显背景色;
- 使用
MeshBasicMaterial临时排除灯光问题; - 添加
AxesHelper和GridHelper; - 检查相机位置。
例如:
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 导入映射;
three和three/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 每一帧到底执行了什么。