跳到主要内容

包体积与 Tree Shaking

PlayCanvas Engine 在 npm 上以 ES 模块形式发布,每个源码文件对应一个模块,且 package.json 声明了 "sideEffects": false。使用 Vite、Rollup、esbuild 或 webpack 等工具打包时,构建工具会沿代码中的导入关系分析,将未被使用的模块排除。这称为 tree shaking。

最终包中包含哪些内容,很大程度上取决于 AppBase 的配置。本页介绍如何让应用只包含实际使用的功能。

工作原理​

代码通过名称引用组件和资源,例如 entity.addComponent('render') 或 new Asset('logo', 'texture', { url })。构建工具无法从这些字符串判断应用需要引擎的哪些部分。

因此,AppBase 只注册 AppOptions 对象中列出的组件系统和资源处理器:

  • 组件系统负责运行一种类型的组件,例如 RenderComponentSystem 运行 render 组件。
  • 资源处理器负责加载一种类型的资源,例如 TextureHandler 加载 texture 资源。

列出的类会由代码导入,因此被包含在包中。没有列出的类,以及仅被这些类使用的代码,都会被排除。

配置 AppBase​

下面为包含网格、相机、灯光、脚本、纹理和 glTF 模型的应用注册所需功能:

main.js
import {
AppBase,
AppOptions,
CameraComponentSystem,
ContainerHandler,
createGraphicsDevice,
DEVICETYPE_WEBGPU,
Keyboard,
LightComponentSystem,
Mouse,
RenderComponentSystem,
ScriptComponentSystem,
ScriptHandler,
TextureHandler,
TouchDevice
} from 'playcanvas';

const canvas = document.getElementById('application');
const device = await createGraphicsDevice(canvas, {
deviceTypes: [DEVICETYPE_WEBGPU]
});

const createOptions = new AppOptions();
createOptions.graphicsDevice = device;

// input devices the application reads
createOptions.mouse = new Mouse(canvas);
createOptions.touch = new TouchDevice(canvas);
createOptions.keyboard = new Keyboard(window);

// component systems and resource handlers the application uses
createOptions.componentSystems = [
RenderComponentSystem,
CameraComponentSystem,
LightComponentSystem,
ScriptComponentSystem
];
createOptions.resourceHandlers = [TextureHandler, ContainerHandler, ScriptHandler];

const app = new AppBase(canvas);
app.init(createOptions);
app.start();

如果使用组件却没有注册对应系统,addComponent 会返回 null,调试版引擎记录 addComponent: System 'sound' doesn't exist。加载资源但没有注册对应处理器时,加载会失败,并报告 No resource handler for asset type。

提示

开发期间,Vite 等设置了 development 导出条件的构建工具会使用引擎调试构建,输出这些错误;生产构建使用发布构建。

组件系统​

为应用添加的每种组件注册对应组件系统。其他依赖列说明该组件还需要哪些功能。

组件系统组件用途其他依赖
RenderComponentSystemrender网格、基本几何体和 glTF 模型中的实体
CameraComponentSystemcamera相机
LightComponentSystemlight方向光、点光源、聚光灯和面光源
ScriptComponentSystemscript脚本以 script 资源形式加载脚本时需要 ScriptHandler
GSplatComponentSystemgsplat高斯泼溅GSplatHandler
ParticleSystemComponentSystemparticlesystem粒子系统加载粒子纹理需要 TextureHandler
AnimComponentSystemanim动画状态图和动画图层加载 animclip 与 animstategraph 资源需要 AnimClipHandler 和 AnimStateGraphHandler
AnimationComponentSystemanimation旧版动画播放,已由 anim 取代AnimationHandler
ModelComponentSystemmodel旧版网格,已由 render 取代ModelHandler
SoundComponentSystemsound声音播放AudioHandler,以及 AppOptions 中的 soundManager
AudioListenerComponentSystemaudiolistener空间音频监听器AppOptions 中的 soundManager
CollisionComponentSystemcollision碰撞形状和触发器ammo.js
RigidBodyComponentSystemrigidbody刚体物理CollisionComponentSystem、ammo.js
JointComponentSystemjoint物理关节RigidBodyComponentSystem、CollisionComponentSystem、ammo.js
ScreenComponentSystemscreen用户界面根节点
ElementComponentSystemelement文本、图像和分组元素ScreenComponentSystem;文本需要 FontHandler,输入需要 AppOptions 中的 elementInput
ButtonComponentSystembutton按钮ElementComponentSystem,以及 AppOptions 中的 elementInput
ScrollViewComponentSystemscrollview可滚动内容ElementComponentSystem,滚动条需要 ScrollbarComponentSystem
ScrollbarComponentSystemscrollbar滚动条ElementComponentSystem
LayoutGroupComponentSystemlayoutgroup子元素布局ElementComponentSystem
LayoutChildComponentSystemlayoutchild布局组中元素的布局设置ElementComponentSystem、LayoutGroupComponentSystem
SpriteComponentSystemsprite2D 精灵及精灵动画加载精灵需要 SpriteHandler、TextureAtlasHandler 和 TextureHandler

资源处理器​

为应用加载的每种资源注册对应资源处理器。

资源处理器资源类型加载内容
TextureHandlertexture图像、HDR 图像和压缩纹理
ContainerHandlercontainerglTF 和 GLB 模型,以及其中的网格、材质、纹理和动画
ScriptHandlerscript定义脚本的 JavaScript 文件
GSplatHandlergsplat高斯泼溅文件
CubemapHandlercubemap立方体贴图
MaterialHandlermaterial以 JSON 保存的材质
RenderHandlerrender引用 container 资源的网格,例如编辑器导出的网格
FontHandlerfont文本元素使用的字体
AudioHandleraudio音频文件
AnimClipHandleranimclipanim 组件使用的动画片段
AnimStateGraphHandleranimstategraphanim 组件使用的动画状态图
AnimationHandleranimation旧版 animation 组件使用的动画
ModelHandlermodel旧版 model 组件使用的模型
SpriteHandlersprite精灵
TextureAtlasHandlertextureatlas精灵使用的纹理图集
SceneHandlerscene编辑器导出的场景
JsonHandlerjsonJSON 数据
TextHandlertext文本文件
BinaryHandlerbinary以 ArrayBuffer 表示的二进制数据

其他选项​

AppOptions 的其他属性也按同样方式添加功能:未设置的功能不会被包含。

选项值用途
graphicsDevicecreateGraphicsDevice 返回的 GraphicsDevice渲染,必需。
mousenew Mouse(canvas)通过 app.mouse 读取鼠标输入
touchnew TouchDevice(canvas)通过 app.touch 读取触摸输入
keyboardnew Keyboard(window)通过 app.keyboard 读取键盘输入
gamepadsnew GamePads()通过 app.gamepads 读取手柄输入
elementInputnew ElementInput(canvas)用户界面元素上的鼠标和触摸输入
soundManagernew SoundManager()通过 sound 和 audiolistener 组件播放声音
lightmapperLightmapper 类运行时烘焙光照贴图
batchManagerBatchManager 类将网格实例合并为批次
xrXrManager 类通过 app.xr 使用 WebXR
assetPrefix字符串添加到每个资源 URL 前的前缀
scriptPrefix字符串添加到每个脚本 URL 前的前缀
scriptsOrder脚本 URL 数组脚本加载顺序
devtoolstrue 或 false应用是否向 PlayCanvas Inspector 等开发者工具声明自身,默认为 true。

没有在此配置的输入设备,在应用中会保持为 null。

控制包体积​

  • **从 playcanvas 导入。**包名解析到按模块发布的构建,便于构建工具执行 tree shaking。playcanvas/build/ 中的单文件构建适用于不使用构建工具的场景,例如通过导入映射使用引擎。
  • **直接使用引擎导出项。**具名导入(import { Entity } from 'playcanvas')和命名空间成员访问(pc.Entity)都支持 tree shaking。将整个命名空间作为值传给函数,例如 setup(pc),会导致 esbuild 等部分构建工具保留整个引擎。
  • **检查包中包含的内容。**esbuild 可通过 --analyze 输出各模块体积,rollup-plugin-visualizer 则可以绘制 Vite 或 Rollup 包的可视化分布图。