在打包工具(vite 为例)的环境下创建 Three.js 项目

3,423 阅读2分钟

0 技术选型

  • vite 2.6 来做开发服务器、打包器
  • vanilla.js 来写 JavaScript 代码
  • css3 来控制页面样式
  • yarn 管理 Three.js 依赖

快速开项目

yarn create vite threejs-esm-demo --template vanilla
cd ./threejs-esm-demo
yarn add three # 主库
yarn add @types/three -D # 类型提示库

1 项目目录结构

+ threejs-esm-demo/
  + node_modules/...
  - index.html
  - main.js
  - style.css
  - ...

2 修改 main.jsstyle.css

main.js

import { 
  PerspectiveCamera,
  Scene,
  BoxGeometry,
  MeshNormalMaterial,
  Mesh,
  WebGLRenderer,
} from 'three'

import './index.css'

let camera
let scene
let renderer
let geometry
let material
let mesh

const init = () => {
  camera = new PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10)
  camera.position.z = 1

  scene = new Scene()
  
  geometry = new BoxGeometry(0.2, 0.2, 0.2)
  material = new MeshNormalMaterial()

  mesh = new Mesh(geometry, material)
  scene.add(mesh)

  renderer = new WebGLRenderer({
    antialias: true
  })
  renderer.setSize(window.innerWidth, window.innerHeight)
  renderer.setAnimationLoop(animation)
  document.querySelector('#app').appendChild(renderer.domElement)
}

const animation = (time) => {
  mesh.rotation.x = time / 2000
  mesh.rotation.y = time / 1000
  
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)

  renderer.render(scene, camera)
}

window.addEventListener("DOMContentLoaded", () => {
  init()
})

style.css

html, body {
  padding: 0;
  margin: 0;
}

#app {
  width: 100vw;
  height: 100vh;
}

2.3 运行

yarn dev 即可在 http://localhost:3000/ 上查看旋转小方块的效果。

yarn build 构建打包至项目 ./dist 目录,并使用 yarn servehttp://localhost:5000/ 上查看生产模式的效果。

3 原理

@types/three 这个包会告诉 VSCode 如何识别 Three.js 的命名空间、模块,也会告诉打包器如何对 three 这个包打包。

不妨在 vite 的配置中把压缩关闭:

import { defineConfig } from 'vite'

export default defineConfig({
  build: {
    minify: false
  }
})

重新打包,你可以在 ./dist/index.<hashcode>.js 文件中的第一行找到这样的代码:

import { P as PerspectiveCamera, S as Scene, B as BoxGeometry, M as MeshNormalMaterial, a as Mesh, W as WebGLRenderer } from "./vendor.ae523e04.js";

打开这个 ./vendor.<hashcode>.js 文件,找到最后几行:

if (typeof window !== "undefined") {
  if (window.__THREE__) {
    console.warn("WARNING: Multiple instances of Three.js being imported.");
  } else {
    window.__THREE__ = REVISION;
  }
}
export { BoxGeometry as B, MeshNormalMaterial as M, PerspectiveCamera as P, Scene as S, WebGLRenderer as W, Mesh as a };

这就是 vite 打包器(当前暂时为 rollup)做的事情,你会发现 vendor.<hashcode>.js 的体积和官方的 Three.js 单文件库体积、内容差不了多少,其实这就是 vite 打包器根据类型库 @types/threethree 库本身打包出来的依赖项,丑是丑了点,没关系,程序能运行就行。

3 下一步

  • 关注 Three.js 的其他插件,例如一些额外的 Loader 类如何被开发模式、生产模式的页面调用以及导入。这个留给读者自己试验;

  • 使用 CDN 加速构建过程和首屏速度。即便 gzip 后只有 100 多 KB,比起 Cesium.js 等庞然大物来说小了不少,但是作为一个有追求的开发者,应该每一步尽可能想到能优化的地方。这个可以查看 vite 的插件,令 vite 排除 three 的打包,并在 index.html 中以 <script> 的形式引入 three;

  • 在 Webpack、Parcel、Rollup 等打包器、构建工具中做尝试,适合老项目。

源代码下载

【微云文件】threejs-esm-demo.zip