主题
从零开始
这页解决三件事:把环境搭起来、把应用跑起来、看懂启动后屏幕上的东西。全程不需要先读任何其他文档,命令跑通之后,你会完成一次真实的图层编辑,并且知道每次改动在内部经过了哪些环节。所有命令以仓库根 mapstudio2/ 为起点。
仓库里有什么
mapstudio2/
├── editor/ # Angular 前端应用本体,日常开发主要在这里
├── server/ # Rust 生产后端:静态托管 + /mock/* 兼容端点 + 上传与档案 API
├── tools/ # e2e 聚合与视觉基线工具链(Playwright + pixelmatch)
├── docs/ # 仓内领域文档(roadmap、spec、analysis、testing)
├── docs-site/ # 本文档站(VitePress)
└── design/ # Expression Engine 落地设计两份日常开发几乎只进出 editor/ 和 tools/ 两个目录。editor/src/app 下约 250 个 TS 文件、7 万多行代码,逐目录职责见目录结构与职责,这里先不用管。
环境要求
| 工具 | 版本 | 什么时候需要 |
|---|---|---|
| Node.js | 22(CI 基准,用 node --version 确认) | 一直需要 |
| npm | 随 Node 安装(本地实测 10.x) | 一直需要,安装依赖要加 --legacy-peer-deps |
| Rust 工具链 | edition 2021 / rust-version 1.85+ | 只在开发 server/ 时需要 |
| Playwright Chromium | npx playwright install chromium | 只在跑 e2e / 视觉基线时需要 |
有个姊妹仓的可选依赖先说明一下:@ng-mfe/core 与 @gmap/* 指向同级目录 ../ng-mfe、../gissdk_onemap,只用于微前端联调。没有这两个目录完全不影响 editor 独立开发,editor/scripts/link-gmap.mjs 在 postinstall 里会自动跳过。
安装与启动
bash
cd editor
npm install --legacy-peer-deps # postinstall 自动处理符号链接,缺姊妹仓时静默跳过
npm run dev # http://localhost:4230两个点提前打招呼:
- 端口是 4230 且 strictPort,被占不会自动换端口而是直接报错。这是故意的,e2e 依赖固定端口。
- vitest 3 与 @angular/build 的 peer 范围有既定冲突,
--legacy-peer-deps是 CI 同款安装方式,不是权宜之计。
启动成功后你会看到类 Mapbox Studio 的三栏工作台。从敲下 npm run dev 到界面可以点,中间发生的事如下图,理解这条线对后面排查"画布为什么是空白"很有帮助:
几个容易被问到的细节:
- 默认装载的是本地 klokantech 基础地图(已中文化)。拉取失败按 demotiles 到内置离线演示样式逐级回退,所以断网也能完整体验编辑器。
- 刷新时如果检测到上次编辑的草稿(localStorage 自动保存,800ms 防抖),会弹恢复提示。恢复就回到刷新前的工作态,连撤销历史都在;放弃则清掉草稿加载默认样式。
- dev 与 preview 环境由
editor/mock/vite-plugin-mock.mjs提供同源/mock/*离线底图端点,端点清单在editor/mock/README.md。
界面三栏导览
自上而下过一遍,每个区域的完整行为留给功能全景:
- 顶栏:样式名(双击重命名)、Share/Open 快捷、Help 下拉、History 撤销时间线与 Compare recent styles。"打开样式"弹窗里有文件选择、路径与 URL 加载,加五个快选:新建空白、Klokantech、demotiles、mock 瓦片、内置离线演示样式。
- 左栏:图层树,支持分组、拖拽排序、底图目录与导入目录。切到 Global 页签则是八个全局面板(投影、光照、3D 地形、天空、雪、雨、辅助选择、设置)。Print 面板打开时整列替换左栏。
- 右栏:属性面板,spec 驱动的全中文 paint/layout 行、Stops 编辑器、表达式构建器。多选图层时变为 Multi-merge 合并面板。
- 画布:地图与周边浮层,包括取色吸管、要素弹层、Debug 面板。hover 与 click 高亮由 feature-state 驱动,不会新增真实图层。
- 状态栏:指针坐标、缩放读数、JSON 按钮,读数全部走 computed。
第一个图层编辑:完整走查
现在动手改点东西,顺便把编辑器最重要的一条内部链路走一遍。目标:给水域图层换个颜色。
- 在左栏图层树找到水面图层(默认底图里通常是 water 或水域相关的行),点选它。右栏变成该图层的属性面板。
- 在 paint 分组里找到颜色属性行(fill-color 或类似),行内有个色块,点开取色器。
- 在 SV 面板拖动选色。注意画布颜色是即时跟随的,不用点确认。
这几十毫秒里内部发生了什么?这是全项目最常走的一条路,五段接力:
接着验证两个配套机制:
- 按 ⌘Z(Ctrl+Z)撤销,画布和属性面板一起回到上一个颜色。拖动取色器的一连串修改被合并成了一条撤销记录,所以一次 ⌘Z 回到拖动之前,不是每像素退一格。
- 刷新页面,会弹「恢复未保存的草稿?」,恢复后刚才的编辑还在,⌘Z 依然可用,因为撤销历史随草稿一起落盘。
这条链路的完整设计(为什么撤销用补丁、为什么地图同步走 diff 而不是整份重载)见架构总览。
本机最小验证
改代码前先确认三个命令全绿,环境就算就绪:
bash
cd editor
npm run typecheck # tsc --noEmit + mfe 入口检查,0 错误
npm run test # vitest 全量单测(tests/ 镜像树 + mock 管线单测)
npm run build # 生产构建到 dist/完整门禁矩阵(覆盖率、e2e、视觉基线)见测试策略。
生产形态试跑
bash
cd editor && npm run verify:prod # vite preview :4231 起产物 + Playwright 冒烟断言
# 或用 Rust server 一体化托管(静态 + /mock/* + 上传 API):
cd server && cargo run --release -- --static ../editor/dist
# 默认 127.0.0.1:2273,运行时上传数据落 server-data/(已 gitignore)跑 e2e 与视觉基线
bash
cd editor && npm run e2e # tools/e2e.mjs:自管 dev server,17 套 Playwright 回归
cd tools && node visual-baseline.mjs # 中文视觉基线,11 状态 0.4% 像素门禁
cd tools && node visual-baseline.mjs --update # 有意做视觉变更时重录基线,PNG 随 PR 提交跑 e2e 前先确认 4230 端口上没有残留的旧 dev server,见下面常见问题。
本文档站
bash
cd docs-site && npm install && npm run dev # 本地预览 http://localhost:5173
cd docs-site && npm run build && npm run preview # 静态产物,构建含死链检查常见第一小时问题
- npm install 报 peer 依赖冲突:用
npm install --legacy-peer-deps,这是 CI 同款,不是规避问题的野路子。 - 4230 端口被占:先
lsof -tiTCP:4230 -sTCP:LISTEN | xargs kill再启动。e2e 整批假红多半也是陈旧进程持有旧的 HMR 状态导致。 - 画布空白且控制台报 Worker failed to load:maplibre-gl 6 的 worker 接线分 dev 与 prod 两路,
npm run dev会自动处理。如果在自建托管里复现,确认 worker 资产以.js落盘且与主包同目录,细节见构建与部署。 - 离线环境画布没底图:在线端点失败后会自动回退内置离线演示样式。想要确定性的离线底图,用「打开样式」弹窗里的「加载本地 mock 瓦片底图」快选(仅 dev server 下可用)。
- 每次刷新都弹草稿恢复提示:程序化装载已有防误存布防(suppressNextSave),正常情况下默认样式不会被写成草稿。如果复现了,说明某条装载链忘了布防,这是需要修的缺陷,不是正常行为。
- 改了组件公共成员名,测试全绿但页面坏了:本项目没有模板类型检查通道,模板里引用不存在的类成员,tsc 和 vitest 都抓不到。改公共成员名必须同步 grep 模板,这条在开发规范里有备案。