template/dev.md
unanmed a01caba0c8 docs: 优化提示文档
Co-authored-by: Copilot <copilot@github.com>
2026-05-06 19:46:54 +08:00

5.5 KiB
Raw Blame History

魔塔样板开发说明

项目结构

  • public: mota-js 样板所在目录
  • packages: 核心引擎代码 monorepo
  • packages-user: 用户代码 monorepo
  • src: 游戏入口代码

依赖关系为单向:srcpackages-userpackagespackagespackages-user 均可独立打包为库模式,src 为游戏的入口代码。

开发环境

  • node.js ^20.0.0 || >=22.0.0
  • pnpm >= 10.0.0
  • 任意支持 ESNext 特性的浏览器

建议使用 vscode,搭配 prettier eslint 插件。

开发说明

  1. 将项目拉取到本地。
  2. 运行 pnpm i 安装所有依赖(如提示运行 pnpm approve-builds,请允许全部)。
  3. 运行 pnpm dev 进入开发环境。

构建说明

命令 说明
pnpm build:packages 以库模式构建 packages 下的所有内容
pnpm build:game 构建为可直接部署的游戏包
pnpm build:lib 以库模式构建 packagespackages-user 下的所有内容
pnpm type 对仓库执行类型检查
pnpm check:circular 对仓库执行循环引用检查

开发原则

模块原则

  • 无副作用:所有模块只包含函数、类、常量的声明,不允许出现导出的变量声明或顶层代码执行,允许但不建议编写类的静态块。
  • 模块初始化:如需初始化,编写一个 createXxx 函数,在 index.ts 中整合后逐级向上传递,直至顶层模块统一执行。
  • 不转发导出:不允许一个文件导出不属于当前 monorepo 或当前文件夹的内容。
  • 无循环引用:不允许出现循环引用。若遇到不得不循环引用的情况,应首先反思接口设计是否存在问题。

命名规则

命名对象 规范
变量、成员、一般常量、方法、函数 小驼峰
类、接口、类型别名、命名空间、泛型、枚举、组件 大驼峰
不变常量 全大写,单词间下划线分隔(如 MAX_COUNT
专有名词缩写(如 HTTPURI 全大写
需被 implements 的接口 大写 I 开头
HTML/CSS 中的 idclass 连字符命名法

不使用下划线命名法。

注释规范

  • 常用属性成员、方法、接口、类型必须添加 jsDoc 注释。
  • 长文件可使用 #region / #endregion 分段以支持折叠。
  • TODO 使用 // TODO:// todo: 格式。
  • 单行注释的 // 与注释内容之间留一个空格;不允许出现非 jsDoc 的多行注释,如需多行注释,使用多个单行注释代替。
  • 注释合理换行:考虑中文字符较宽,建议每 4060 个字符在标点符号后换行,不允许在句中换行;参数注释换行后保持对齐。
  • 单行注释结尾不加句号;较长的多行注释结尾可加句号。
  • 一般不建议给接口、类型别名或类本身写注释(不好看),特殊情况除外。

类型规范

  • 不允许出现非必要的 any 类型。
  • 所有类的成员必须显式声明类型。
  • 无法避免类型错误时,使用 // @ts-expect-error 标记并说明原因。
  • 未使用的变量或方法以下划线开头命名。
  • 合理使用 readonlyprotectedprivate 关键字。
  • 可选参数过多时,考虑改用对象参数。
  • 尽量避免 as 类型断言,除非必要。

其他要求

  • 严格遵循 eslint 配置,不允许出现 eslint 报错。
  • 尽量不使用 ?. 运算符,仅推荐在以下两种场景中使用:
    • 副作用函数调用,如 this.obj?.func()this.obj.func?.()
    • 对象 Required 化,如 { value: obj?.value ?? 0 }
  • 只进行必要的非空判断,非必要时直接使用非空断言 !
  • 除非参数要求传入函数等情况,不建议在函数内定义局部函数。
  • 语句尽量不换行,除非必要,尤其注意三元运算符与 private readonly 类成员。

双端分离

样板将渲染端与数据端彻底分离:

  • 数据端:可在 node 环境中单独运行,可直接用于录像验证,不负责任何渲染逻辑。
  • 渲染端:仅负责向数据端发送消息,不负责任何逻辑运算。
层级 说明
@user/data-base 数据端系统层 负责数据端核心系统
@user/data-state 数据端实现层 依赖系统层实现完整的游戏实例
@user/client-base 渲染端系统层 负责渲染端核心系统
@user/client-modules 渲染端实现层 依赖系统层实现客户端的渲染与用户交互

数据端允许调用渲染端代码,但必须使用全局接口 Mota.r(() => {}) 包裹。除非必要,否则不建议在数据端调用渲染端代码。