Files
esengine/packages/build-config
YHH c3b7250f85 refactor(plugin): 重构插件系统架构,统一类型导入路径 (#296)
* 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 失败
2025-12-08 21:10:57 +08:00
..
2025-12-01 22:28:51 +08:00
2025-12-01 22:28:51 +08:00

@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 中不能:

  • 导入 reactreact-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 预设

  1. 安装依赖:
pnpm add -D @esengine/build-config vite vite-plugin-dts
  1. 替换 rollup.config.jsvite.config.ts
import { pluginPreset } from '@esengine/build-config/presets';

export default pluginPreset({
    root: __dirname,
    hasCSS: true
});
  1. 更新 package.json 的 scripts
{
    "scripts": {
        "build": "vite build",
        "build:watch": "vite build --watch"
    }
}
  1. 删除旧的 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)[] [] 额外的外部依赖