* refactor(plugin): 重构插件系统架构,统一类型导入路径 ## 主要更改 ### 新增 @esengine/plugin-types 包 - 提供打破循环依赖的最小类型定义 - 包含 ServiceToken, createServiceToken, PluginServiceRegistry, IEditorModuleBase ### engine-core 类型统一 - IPlugin<T> 泛型参数改为 T = unknown - 所有运行时类型(IRuntimeModule, ModuleManifest, SystemContext)在此定义 - 新增 PluginServiceRegistry.ts 导出服务令牌相关类型 ### editor-core 类型优化 - 重命名 IPluginLoader.ts 为 EditorModule.ts - 新增 IEditorPlugin = IPlugin<IEditorModuleLoader> 类型别名 - 移除弃用别名 IPluginLoader, IRuntimeModuleLoader ### 编辑器插件更新 - 所有 9 个编辑器插件使用 IEditorPlugin 类型 - 统一从 editor-core 导入编辑器类型 ### 服务令牌规范 - 各模块在 tokens.ts 中定义自己的服务接口和令牌 - 遵循"谁定义接口,谁导出 Token"原则 ## 导入规范 | 场景 | 导入来源 | |------|---------| | 运行时模块 | @esengine/engine-core | | 编辑器插件 | @esengine/editor-core | | 服务令牌 | @esengine/engine-core | * refactor(plugin): 完善服务令牌规范,统一运行时模块 ## 更改内容 ### 运行时模块优化 - particle: 使用 PluginServiceRegistry 获取依赖服务 - physics-rapier2d: 通过服务令牌注册/获取物理查询接口 - tilemap: 使用服务令牌获取物理系统依赖 - sprite: 导出服务令牌 - ui: 导出服务令牌 - behavior-tree: 使用服务令牌系统 ### 资产系统增强 - IAssetManager 接口扩展 - 加载器使用服务令牌获取依赖 ### 运行时核心 - GameRuntime 使用 PluginServiceRegistry - 导出服务令牌相关类型 ### 编辑器服务 - EngineService 适配新的服务令牌系统 - AssetRegistryService 优化 * fix: 修复 editor-app 和 behavior-tree-editor 中的类型引用 - editor-app/PluginLoader.ts: 使用 IPlugin 替代 IPluginLoader - behavior-tree-editor: 使用 IEditorPlugin 替代 IPluginLoader * fix(ui): 添加缺失的 ecs-engine-bindgen 依赖 UIRuntimeModule 使用 EngineBridgeToken,需要声明对 ecs-engine-bindgen 的依赖 * fix(type): 解决 ServiceToken 跨包类型兼容性问题 - 在 engine-core 中直接定义 ServiceToken 和 PluginServiceRegistry 而不是从 plugin-types 重新导出,确保 tsup 生成的类型声明 以 engine-core 作为类型来源 - 移除 RuntimeResolver.ts 中的硬编码模块 ID 检查, 改用 module.json 中的 name 配置 - 修复 pnpm-lock.yaml 中的依赖记录 * refactor(arch): 改进架构设计,移除硬编码 - 统一类型导出:editor-core 从 engine-core 导入 IEditorModuleBase - RuntimeResolver: 将硬编码路径改为配置常量和搜索路径列表 - 添加跨平台安装路径支持(Windows/macOS/Linux) - 使用 ENGINE_WASM_CONFIG 配置引擎 WASM 文件信息 - IBundlePackOptions 添加 preloadBundles 配置项 * fix(particle): 添加缺失的 ecs-engine-bindgen 依赖 ParticleRuntimeModule 导入了 @esengine/ecs-engine-bindgen 的 tokens, 但 package.json 中未声明该依赖,导致 CI 构建失败。 * fix(physics-rapier2d): 移除不存在的 PhysicsSystemContext 导出 PhysicsRuntimeModule 中不存在该类型,导致 type-check 失败
@esengine/build-config
ES Engine 统一构建配置包,提供标准化的 Vite 配置预设和共享插件。
快速开始
创建新包
使用脚手架工具快速创建新包:
# 交互式创建
node scripts/create-package.mjs
# 或指定参数
node scripts/create-package.mjs my-plugin --type plugin
包类型
| 类型 | 说明 | 示例 |
|---|---|---|
runtime-only |
纯运行时库,不含编辑器代码 | core, math, components |
plugin |
插件包,同时有 runtime 和 editor 入口 | ui, tilemap, behavior-tree |
editor-only |
纯编辑器包,仅用于编辑器 | editor-core, node-editor |
使用预设
1. runtime-only(纯运行时包)
// vite.config.ts
import { runtimeOnlyPreset } from '@esengine/build-config/presets';
export default runtimeOnlyPreset({
root: __dirname
});
目录结构:
packages/my-lib/
├── src/
│ └── index.ts # 主入口
├── vite.config.ts
└── package.json
2. plugin(插件包)
// vite.config.ts
import { pluginPreset } from '@esengine/build-config/presets';
export default pluginPreset({
root: __dirname,
hasCSS: true // 如果有 CSS 文件
});
目录结构:
packages/my-plugin/
├── src/
│ ├── index.ts # 主入口(导出全部)
│ ├── runtime.ts # 运行时入口(不含 React!)
│ ├── MyRuntimeModule.ts
│ └── editor/
│ ├── index.ts # 编辑器模块
│ └── MyPlugin.ts
├── plugin.json # 插件描述文件
├── vite.config.ts
└── package.json
生成的 exports:
{
".": "./dist/index.js",
"./runtime": "./dist/runtime.js",
"./editor": "./dist/editor/index.js",
"./plugin.json": "./plugin.json"
}
3. editor-only(纯编辑器包)
// vite.config.ts
import { editorOnlyPreset } from '@esengine/build-config/presets';
export default editorOnlyPreset({
root: __dirname,
hasReact: true,
hasCSS: true
});
共享插件
CSS 注入插件
将 CSS 内联到 JS 中,避免单独的 CSS 文件:
import { cssInjectPlugin } from '@esengine/build-config/plugins';
export default defineConfig({
plugins: [cssInjectPlugin()]
});
阻止编辑器代码泄漏
在运行时构建中检测并阻止编辑器代码被打包:
import { blockEditorPlugin } from '@esengine/build-config/plugins';
export default defineConfig({
plugins: [
blockEditorPlugin({ bIsRuntimeBuild: true })
]
});
Runtime vs Editor 分离规则
✅ runtime.ts 中可以:
- 导入 @esengine/ecs-framework
- 导入 @esengine/ecs-components
- 导入其他包的
/runtime路径
❌ runtime.ts 中不能:
- 导入
react、react-dom - 导入
@esengine/editor-core - 导入
lucide-react等 UI 库 - 导入任何包的
/editor路径
示例
// ✅ 正确
import { Core } from '@esengine/ecs-framework';
import { UIRuntimeModule } from '@esengine/ui/runtime';
// ❌ 错误 - 会把编辑器代码打包进来
import { UIPlugin } from '@esengine/ui'; // 主入口包含编辑器
import { UIPlugin } from '@esengine/ui/editor'; // 直接导入编辑器
import React from 'react'; // React 不应在运行时
迁移现有包
从 Rollup 迁移到 Vite 预设
- 安装依赖:
pnpm add -D @esengine/build-config vite vite-plugin-dts
- 替换
rollup.config.js为vite.config.ts:
import { pluginPreset } from '@esengine/build-config/presets';
export default pluginPreset({
root: __dirname,
hasCSS: true
});
- 更新
package.json的 scripts:
{
"scripts": {
"build": "vite build",
"build:watch": "vite build --watch"
}
}
- 删除旧的 rollup 配置和依赖。
API 参考
runtimeOnlyPreset(options)
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| root | string | - | 包根目录(必填) |
| entry | string | 'src/index.ts' | 入口文件 |
| external | (string|RegExp)[] | [] | 额外的外部依赖 |
| viteConfig | Partial | {} | 额外的 Vite 配置 |
pluginPreset(options)
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| root | string | - | 包根目录(必填) |
| entries.main | string | 'src/index.ts' | 主入口 |
| entries.runtime | string | 'src/runtime.ts' | 运行时入口 |
| entries.editor | string | 'src/editor/index.ts' | 编辑器入口 |
| hasCSS | boolean | false | 是否包含 CSS |
| hasPluginJson | boolean | true | 是否导出 plugin.json |
| external | (string|RegExp)[] | [] | 额外的外部依赖 |
editorOnlyPreset(options)
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| root | string | - | 包根目录(必填) |
| entry | string | 'src/index.ts' | 入口文件 |
| hasReact | boolean | true | 是否包含 React |
| hasCSS | boolean | false | 是否包含 CSS |
| external | (string|RegExp)[] | [] | 额外的外部依赖 |