乐于分享
好东西不私藏

从本地设计到可交付源码:VTJ 项目出码与发布云端实践

从本地设计到可交付源码:VTJ 项目出码与发布云端实践

低代码工具最常被质疑的问题之一是:项目最终是否仍然属于开发者?

如果设计结果只能运行在特定平台中,那么一旦离开平台,页面、组件和业务逻辑便难以继续维护。VTJ 从设计之初就将 DSL 与标准 Vue 源码之间的双向转换作为核心能力,并在此基础上提供“项目出码”和“发布云端”两条不同的交付路径。

它们分别解决两个问题:

  • 项目出码:把设计成果转换成可下载、可运行、可继续开发的源码工程。
  • 发布云端:把本地项目 DSL 同步到 VTJ 在线项目的开发环境,在本地开发与在线设计之间建立连接。

本文将结合 VTJ 的实际实现,介绍这两项能力的用途、工作原理和使用方式。

为什么需要两种交付方式

在真实开发中,低代码项目通常有两种去向。

第一种是“交付源码”。项目完成后,团队希望得到标准前端工程,继续使用 Git、IDE、CI/CD 和现有部署体系维护。

第二种是“跨环境协作”。开发者可能先在本地工程中使用 VTJ 设计器完成页面,再把设计成果同步到在线环境,交给其他成员继续编辑、预览、创建版本或出码。

这两个需求看似相近,实际处理的是不同层次的数据:

功能
处理对象
目标位置
是否影响线上版本
发布文件
当前页面或区块
本地 Vue 文件
整站发布
本地全部页面和区块
本地 Vue 文件
发布云端
Project、Material、File DSL
在线项目 dev 环境
项目出码
完整项目 DSL 和平台模板
可下载源码 ZIP
发布应用
dev DSL 创建正式版本
在线生产版本

尤其需要注意:“发布云端”不是“发布上线”。它只更新在线项目的开发环境,不创建版本,也不会改变当前线上应用。

项目出码:从 DSL 生成完整源码工程

VTJ 设计器中的页面、区块、依赖、路由和项目配置,首先以 DSL 的形式保存。

执行“项目出码”时,VTJ 会根据项目平台选择对应工程模板。目前支持:

  • Web
  • H5
  • UniApp

随后,出码服务会读取项目开发环境中的三类核心数据:

Project DSL

Project DSL 描述项目整体结构,包括:

  • 项目编码和名称
  • 项目平台
  • 页面和区块目录
  • 首页配置
  • 依赖列表
  • 全局变量
  • API 与元数据
  • Web、H5 或 UniApp 平台配置

Project DSL 主要负责描述“项目中有哪些内容”,不会直接内嵌每个页面的完整 DSL。

Material DSL

Material DSL 保存设计器实际使用的物料描述,包括组件名称、属性、事件、插槽和依赖来源。

代码生成器依赖这部分信息,将 DSL 节点正确转换成组件引用、属性绑定和事件处理代码。

File DSL

每个页面和自定义区块分别保存为一份 File DSL。

出码过程中,VTJ 会逐个读取这些文件,通过 @vtj/coder 转换成 Vue 单文件组件,再写入目标工程。

出码工程包含什么

VTJ 不是简单导出一批孤立的 .vue 文件,而是在对应平台的标准项目模板上生成完整工程。

生成内容主要包括:

  • 项目及文件 DSL
  • 页面和区块对应的 Vue 源码
  • 项目依赖
  • 路由和页面配置
  • VTJ 本地开发配置
  • 平台启动文件
  • UniApp 的 pages.json
  • UniApp 的 manifest.json
  • UniApp 的 App.vue

对于项目中额外使用的依赖,出码服务还会将其合并到生成工程的 package.json 中。

最终工程被压缩成 ZIP,并生成临时下载地址。开发者下载后可以直接安装依赖、运行、修改和纳入自己的 Git 仓库。

这也是 VTJ 避免平台锁定的关键:DSL 是设计阶段的表达形式,标准 Vue 工程才是最终可持续维护的交付物。

发布云端:连接本地项目与在线设计器

VTJ 本地版可以直接嵌入现有 Vue 项目。开发者在本地运行项目后,通过 /__vtj__/ 进入设计器,设计数据保存在项目的 .vtj 目录中。

现在,本地设计器的“发布”下拉菜单增加了“发布云端”:

发布├── 发布文件├── 整站发布├── 发布云端└── 发布模板

点击“发布云端”后,VTJ 会将本地项目完整的 DSL 数据同步到同编码在线项目的 dev 环境。

本地项目如何匹配在线项目

本地项目编码来自 package.json

{"vtj":{"id":"demo-app","name":"示例应用","platform":"web"}}

如果没有设置 vtj.id,VTJ 会使用 package.json 中的项目名称。

发布云端要求:

  • 本地项目 ID 与在线应用 code 完全一致。
  • 本地项目与在线项目的平台一致。
  • 当前用户是应用创建人、协作者或超级管理员。

这种显式匹配方式没有引入额外的项目映射文件,项目身份仍然由已有的 VTJ 配置决定。

发布云端会同步哪些数据

发布时,本地设计器会组装以下数据:

{  project,  materials,  files}

其中:

  • project
     来自当前项目模型。
  • materials
     来自设计器已经加载的物料映射。
  • files
     包括项目中的页面、布局和本地 Schema 区块。

为了避免丢失尚未落盘的编辑内容,当前正在编辑的文件会直接从设计器内存模型中读取;其他文件则通过本地文件服务加载。

预置区块、插件区块和 URL Schema 不会被当成本地 File DSL 重复上传。

为什么采用镜像同步

如果发布云端只是逐条新增或更新 DSL,会出现一个容易被忽略的问题:本地已经删除的页面,可能仍然残留在云端数据库中。

这些残留记录虽然不一定立即显示在页面目录里,但后续创建应用版本或项目出码时,可能继续被处理。

因此 VTJ 采用镜像替换策略:

  1. 完整校验上传数据。
  2. 开启数据库事务。
  3. 删除目标项目原有的 Project、Material 和 File dev DSL。
  4. 写入本次上传的完整 DSL。
  5. 提交事务。

整个过程要么全部成功,要么全部回滚,不会产生只上传了一半的项目。

同步只处理核心项目 DSL,不删除在线设计器中的 history 和 history-item,从而避免清理项目编辑历史。

安全与完整性校验

发布云端属于覆盖性操作,因此服务端不会直接信任客户端传入的项目编码。

实际同步前会完成以下检查:

  • 登录 Token 是否有效。
  • 用户是否拥有目标项目的编辑权限。
  • 本地项目编码是否与在线应用编码一致。
  • 项目平台是否一致。
  • Project DSL 结构是否合法。
  • 页面和区块 ID 是否有效且唯一。
  • 每个项目文件是否都有对应 File DSL。
  • 是否包含不属于当前项目的额外文件。
  • 上传数据是否超过大小限制。

只有所有检查通过后,事务同步才会开始。

本地设计器也会在操作前明确提示:发布云端将覆盖在线项目开发环境中尚未发布的修改,但不会影响当前线上版本。

源码模式页面的边界

VTJ 本地版支持源码模式页面,但源码模式页面的核心内容是本地 Vue 文件,而不是一份可以在在线设计器中完整还原的 DSL。

因此,当前项目包含源码模式页面时,“发布云端”会主动终止并提示:

源码模式页面暂不支持发布云端。

这项限制可以避免同步出一个在线设计器无法完整加载和编辑的残缺项目。

项目出码和本地整站发布不受这一限制,因为源码文件原本就在本地工程中。

推荐工作流

结合项目出码与发布云端,可以形成一条完整的开发路径:

本地工程开发    ↓VTJ 本地设计器编辑    ↓发布云端    ↓在线预览与协作    ↓创建应用版本    ↓项目出码或发布上线

一种典型协作方式是:

  1. 在 VTJ 在线平台创建应用并确定应用编码。
  2. 在本地项目的 package.json 中配置相同的 vtj.id
  3. 使用本地设计器完成页面和区块开发。
  4. 点击“发布云端”,覆盖在线项目 dev DSL。
  5. 团队成员在在线设计器中继续预览或编辑。
  6. 需要独立交付时执行“项目出码”。
  7. 需要更新在线应用时,再创建版本并发布应用。

本地工程与在线平台并不是两套割裂的开发方式。DSL 让设计成果可以在两个环境间传递,而项目出码则让最终结果重新回到标准源码工程。

写在最后

VTJ 对“发布”的理解并不只是部署。

发布文件和整站发布面向本地源码生成;发布云端面向开发环境同步;项目出码面向独立工程交付;发布应用才真正涉及线上版本。

通过拆分这些能力,VTJ 希望同时满足三类开发者:

  • 希望用可视化方式提高页面开发效率的人。
  • 希望在本地 IDE 与在线设计器之间协作的人。
  • 重视源码所有权,不愿被低代码平台绑定的人。

设计器可以提高开发效率,但最终代码、工程和交付方式仍应掌握在开发者手中。这正是 VTJ 项目出码与发布云端功能希望解决的问题。

项目地址:https://gitee.com/newgateway/vtj