主题
构建与部署
从源码到能用的服务,主干只有三步:npm run build 出 dist、Rust server 托管、打开浏览器验证。但真正会卡住人的都在支线上:worker 资产必须是 .js、mock 端点不进产物、npm 安装要 --legacy-peer-deps。这一页按流水线顺序讲,支线坑穿插在对应位置。
先看全流程
日常开发不需要走完全程,npm run dev(:4230,strictPort)就够;下面各节是每个环节的细节。
构建产物长什么样
- 分包按 manualChunks 切:
angular-*.js(Angular 运行时 + rxjs)、maplibre-*.js(最大的一块)、monaco-*.js(JSON 编辑器,只在打开时动态 import,不进首屏)、vendor-*.js、index-*.{js,css},sourcemap 开、target es2022。业务代码改动不会打爆三方缓存。 assets/maplibre-gl-worker.js与maplibre-gl-shared.js显式命名落盘:vite 配置里的maplibreWorkerAssetsPlugin从 node_modules 逐字读取 maplibre-gl 的发行文件,改写 worker 内部相对 import 后发射。找不到预期字面量会直接抛错——这是故意的,防止上游结构漂移造成静默劣化。fonts/、styles/从public/拷贝。- 构建产物里没有
/mock/*端点。mock 是 dev/preview 的 vite 插件,生产必须由 Rust server 或反代承接。
为什么 worker 必须是 .js
这里有个部署时最典型的坑,值得单独讲。maplibre-gl 6 是 ESM-only 发行版,它的 worker 是 module 型 Worker,浏览器对 ES module 脚本强制做 MIME 校验。.mjs 扩展名的 MIME 映射依赖静态服务器的配置——旧版 mime 表和 nginx 默认表普遍缺 .mjs,落到 octet-stream 就拒载 worker,表现是地图空白。.js 在所有服务器上都是 text/javascript,从根上绕开这个兼容面(ADR-09)。所以升级 maplibre-gl 后如果构建抛"资产改写失败",按报错同步 vite.config.ts 的 WORKER_ASSETS 配置,不要绕过插件。
生产 server 部署
Rust server(axum 0.8 + tokio)是单体形态:静态托管 + mock 兼容端点 + 上传/档案 API,一个进程让编辑器完整跑起来。瓦片合成、PNG 编解码、sprite 拼装都是 crate 内实现,没有图像处理外部依赖。
推荐用仓库根的一键脚本:
bash
tools/build-server.sh # editor 构建 → 拷 dist 到 server/static → cargo build --release
tools/build-server.sh --run # 构建后直接启动
tools/build-server.sh --skip-web # 前端 dist 已新鲜时跳过前端构建或者手动指定目录托管:
bash
cd editor && npm run build
cd ../server && cargo run --release -- --static ../editor/dist
# 默认 127.0.0.1:2273;不传 --static 时工作目录存在 ./static 即自动采用CLI 参数一览:--listen(默认 127.0.0.1:2273)、--config <yaml>、--static <dir>、--assets <dir>(默认 ./assets)、--data-dir <dir>(默认 ./server-data)。
server 提供的东西:
- 静态托管带 SPA 历史回退,
.mjs/.js显式text/javascriptMIME(worker 兼容面的服务端半边,自带就不用操心 Nginx 配置)。 /mock/*兼容端点(与 dev mock 七类逐项对齐)加规范路径/tiles/*、/fonts/*、/sprite*。- 上传与数据档案 API(
/api/fonts、/api/sprite、/api/tiles/{source}/schema),运行时上传数据落server-data/(gitignored,重启不丢)。 - 可选
martin-pgfeature:内嵌 Martin 连 PG 矢量瓦片;默认反代形态零额外构建。接口全景见server/API.md。
双入口与 MFE 联调
编辑器有两个浏览器入口:standalone 的 src/main.ts(自动引导),和 ng-mfe Portal 子应用的 src/mfe.main.ts(不自动引导,注册为 defineMfeApp('mapstudio'))。后者只有做 Portal 联调才需要:起 editor dev(:4230)和 ng-mfe portal dev(:4200,#/apps/mapstudio),跑 node tools/verify-portal.mjs 验证。姊妹仓 ../gissdk_onemap 与 ../ng-mfe 不在场时,相关检查自动跳过,编辑器独立开发不受影响。npm run typecheck 末段的 mfe 专项检查同理会自动跳过。
CI/CD
ci.yml(PR + push main):quality(typecheck → vitest --coverage → build)→ e2e-smoke(verify-prod 生产冒烟)→ e2e-usecases(用例双向匹配 + 11 套)→ docs(docs-site 构建,死链即红)。门禁链的图解见测试策略。nightly.yml(每日 UTC 18:00):全量 17 套 e2e + 视觉基线 11 态,diff 产物留 14 天。- 没有发布流水线:不发 npm 包、不推镜像、不上云,部署就是"构建 + 起进程"。
部署检查单
部署后按序确认,每步都有对应的自动化工具可以先跑:
GET /healthz探活通过。- 打开首页:地图渲染、图层树渲染、控制台零 pageerror(本地可先跑
npm run verify:prod覆盖同款断言)。 - 底图与地形端点:
/tiles/planet、/tiles/terrain返回 TileJSON;样式里引用的绝对 URL 按对外 Host 正确拼接。 - 按需验证上传 API:
/api/fonts、/api/sprite、/api/tiles有响应。 - 反代场景:确认
.mjs/.jsMIME 与 SPA 历史回退。直接用 Rust server 则跳过。
构建部署域的高频故障(worker MIME、/mock/* 404、peer 冲突、maplibre 升级构建抛错、子路径部署)集中在常见问题。