- 后端
- 前端
- 云原生
【免费下载链接】hedgedoc
HedgeDoc - Ideas grow better together
本文基于 docs/content/how-to/develop/frontend.md 编写,系统梳理 HedgeDoc 前端(Next.js + React + Redux)开发中的环境变量配置、单元测试与 Cypress E2E 测试流程、打包产物分析与生产环境调试技巧。读完本文,你将掌握HD_BASE_URL等关键环境变量的语义与源码级行为、完整跑通测试套件的命令序列,以及无需重新构建即可在生产环境开启调试日志的方法。
前端进程识别的环境变量
HedgeDoc 前端是一个 Next.js 应用(源码位于 frontend),其启动与构建行为由一组HD_*/NEXT_PUBLIC_*环境变量控制。官方文档给出的完整变量清单如下:
| 变量名 | 可取值 | 说明 |
|---|---|---|
HD_BASE_URL | 任意带协议、域名(可含目录与端口)的 URL,必须以斜杠结尾,例如http://localhost:3001/ | 前端对外暴露的访问地址。必填,服务端渲染(SSR)需要据此生成资源(assets)URL。仅在 production 模式需要手动设置 |
HD_RENDERER_BASE_URL | 与HD_BASE_URL格式相同 | 渲染器(renderer)使用独立域名时设置。出于安全考虑推荐让渲染器与编辑器分属不同域名,但非强制。可选,缺省时回退到HD_BASE_URL |
NEXT_PUBLIC_USE_MOCK_API | true、false | 激活模拟后端(mocked backend) |
NEXT_PUBLIC_TEST_MODE | true、false | 激活用于测试套件定位元素的额外 HTML 属性 |
HD_BASE_URL:SSR 资源地址的唯一来源
HD_BASE_URL是唯一必填项,前端进程会用它生成编辑器、渲染器以及内部 API 的完整地址。其底层实现在 frontend/src/utils/base-url-from-env-extractor.ts 中:BaseUrlFromEnvExtractor类会先以parseUrl(来自@hedgedoc/commons,实现见 commons/src/parse-url/parse-url.ts)解析HD_BASE_URL,随后依次解析可选的HD_RENDERER_BASE_URL与HD_INTERNAL_API_URL,并将三者缓存为BaseUrls供全局消费:
- 解析失败(非法 URL)会直接抛出错误,例如
undefined isn't a valid URL; - 在 frontend/src/utils/base-url-from-env-extractor.spec.ts 的单元测试中还验证了:包含子目录的 URL(如
https://editor.example.org/asd/)会被拒绝并抛出Subdirectories are not allowed,因此生产部署时应把前端放在域名根路径或独立端口上; - 结果会被缓存,后续
extractBaseUrls()调用直接返回缓存值,避免重复解析。
值得注意的是,源码中还存在第三个可选项HD_INTERNAL_API_URL(用于指定内部 API 地址,测试可见于同一 spec 文件)。虽然官方文档的环境变量表格未将其列出,但从代码结构看它同样是BaseUrls的一个组成部分,需要隔离内部 API 时可以参考该变量。
HD_RENDERER_BASE_URL:编辑器与渲染器解耦
HD_RENDERER_BASE_URL的取值格式与HD_BASE_URL完全相同。源码中通过extractUrlFromEnv('HD_RENDERER_BASE_URL').orElse(editorBaseUrl)实现回退逻辑:未设置时渲染器直接复用编辑器的地址。对应单元测试(should copy editor base url to renderer base url if url is omitted)验证了这一行为。
将渲染器部署到独立域名是官方推荐的安全实践——这样编辑器与渲染器之间的 iframe 通信可以获得更清晰的来源隔离(HedgeDoc 的渲染器通过 iframe 承载,相关实现可参考 frontend/src/components/common/renderer-iframe/renderer-iframe.tsx)。
NEXT_PUBLIC_*:编译期注入的构建开关
所有以NEXT_PUBLIC_开头的变量都会在构建阶段被编译进产物,编译后无法再修改,因此不能通过运行时注入覆盖。其判定逻辑集中在 frontend/src/utils/test-modes.js(该文件特意保留为.js,因为next.config.js在构建阶段需要引用它):
NEXT_PUBLIC_TEST_MODE→isTestModeNEXT_PUBLIC_USE_MOCK_API→isMockModeNODE_ENV === 'development'→isDevModeANALYZE→isProfilingMode
test-modes.js中isPositiveAnswer的取值判定支持yes、1、true(大小写不敏感)三种真值,也就是说NEXT_PUBLIC_TEST_MODE=1同样生效。
NEXT_PUBLIC_TEST_MODE激活的“额外 HTML 属性”由 frontend/src/utils/cypress-attribute.ts 提供:cypressId()在测试模式下向元素注入data-cypress-id属性,cypressAttribute()注入data-cypress-前缀的自定义属性;非测试模式下这些函数返回空对象/undefined,对生产 DOM 零污染。
如何正确设置这些变量:使用官方 npm 任务
官方文档明确建议:不要手动设置这些变量,而应使用设计好的 npm 任务。这是因为 Mock API 的启用还牵涉到构建脚本对src/pages/api目录的特殊处理。
查看 frontend/package.json 中的脚本定义,可以看到完整的任务矩阵:
| 任务 | 作用 |
|---|---|
pnpm run build | 生产构建(NODE_ENV=production) |
pnpm run build:mock | 以NEXT_PUBLIC_USE_MOCK_API=true构建,产物内置模拟 API |
pnpm run build:test | 以NODE_ENV=test+NEXT_PUBLIC_TEST_MODE=true构建测试版 |
pnpm run start:dev | next dev开发模式,端口默认 3001(HD_FRONTEND_PORT可覆盖) |
pnpm run start:dev:mock | 开发模式 + 模拟后端,并预设HD_BASE_URL/HD_RENDERER_BASE_URL |
pnpm run start:dev:test | 开发模式 + 测试模式(供 E2E 使用) |
构建脚本 frontend/build.sh 揭示了 Mock API 的机制:构建时若设置了NEXT_PUBLIC_USE_MOCK_API,则保留src/pages/api(模拟接口目录);否则将其移动到临时目录、产出不含 Mock API 的正式包。这也是“使用 designated npm tasks”比手动设置变量更安全的原因——手动设置可能让构建脚本处于不一致的状态。
每日重置的 UI 演示实例
如果你对 HedgeDoc 新版 UI 感兴趣,官方维护着一个每日重置的演示实例(即文档中提到的 HedgeDoc.dev 演示站),每天重置数据、不做持久化,适合快速体验编辑器、渲染器与幻灯片等前端界面效果。注意该实例仅供体验 UI,不适合存放重要数据;如需长期使用请自行部署。
运行测试
单元测试:Jest
HedgeDoc 前端的单元测试基于 Jest,配置见 frontend/jest.config.ts。运行方式极简:
pnpm run test该命令会以NODE_ENV=test环境启动 jest(见 frontend/package.json 中test脚本)。开发过程中还可以使用:
pnpm run test:watch # 监听模式,文件变更自动重跑 pnpm run test:ci # CI 模式,带覆盖率收集(--coverage)测试代码与源码同目录存放、以.spec.ts命名,例如前面提到的 frontend/src/utils/base-url-from-env-extractor.spec.ts,以及 frontend/src/utils/logger.spec.ts、frontend/src/utils/format-date.spec.ts 等,覆盖了工具函数与配置解析等核心逻辑。
E2E 测试:Cypress
端到端测试使用 Cypress,测试用例位于 frontend/cypress/e2e(如documentTitle.spec.ts、fileUpload.spec.ts、permissions.spec.ts等,覆盖了文档标题、文件上传、权限等真实用户场景)。
官方推荐的标准流程如下:
以测试模式启动前端(
test变体是强制要求):pnpm run start:dev:test或者先用测试构建产出再启动:
pnpm run build:test pnpm run start为什么必须用
:test变体?因为只有设置了NEXT_PUBLIC_TEST_MODE=true,组件才会通过cypressId()渲染data-cypress-id定位属性(见 frontend/src/utils/cypress-attribute.ts),Cypress 才能稳定地按 ID 抓取元素。打开 Cypress 测试加载器:
pnpm run test:e2e:open选择浏览器并运行测试套件。
如需在无头(headless)浏览器中运行全部测试:
pnpm run test:e2eCypress 配置见 frontend/cypress.config.ts:baseUrl固定为http://127.0.0.1:3001/,默认命令超时 15 秒。此外,test:e2e:ci脚本(cypress run --record --parallel)可用于 CI 环境下的并行执行与结果记录。E2E 测试辅助逻辑(如visit-test-editor.ts通过cy.intercept拦截api/private/notes/test的模拟响应)位于 frontend/cypress/support,编写新用例时可参考。
Bundle 分析:检查产物优化空间
构建后可以分析生产打包产物,定位体积与优化问题:
pnpm run analyze该命令对应 package.json 中的cross-env ANALYZE=true pnpm run build --profile——先以--profile参数构建(这一步会覆盖已有的构建产物),再输出分析结果。随后在浏览器中打开生成的:
.next/server/analyze/server.html即可直观查看各 chunk 与模块的体积构成。test-modes.js中的isProfilingMode正是由ANALYZE变量驱动,用于在构建期启用打包分析与性能埋点。
生产环境开启调试日志
HedgeDoc 前端内置了一个带时间戳与作用域前缀的Logger(实现见 frontend/src/utils/logger.ts)。其debug()方法默认不输出,但在以下三种情况下会启用:
- 开发模式(
isDevMode) - 测试模式(
isTestMode) - 浏览器
localStorage中debugLogging键被置为真值
也就是说,无需重新构建即可在任意生产实例上开启调试输出。官方文档给出的方法是在浏览器控制台执行:
window.localStorage.setItem("debugLogging", "true");执行后刷新页面,Logger.debug(...)的日志便会以带颜色的格式化时间戳输出(源码中prefix()为浏览器环境生成了%c样式前缀)。想关闭时,在控制台清除该键即可:
window.localStorage.removeItem("debugLogging");这在排查渲染器 iframe、实时协作(Yjs/WebSocket)等前端疑难问题时非常实用。
小结
HedgeDoc 前端开发的核心要点可归纳为:环境变量分两类——运行期必填的HD_BASE_URL/HD_RENDERER_BASE_URL与编译期注入的NEXT_PUBLIC_*开关,前者由BaseUrlFromEnvExtractor解析校验,后者驱动 Mock API 与测试模式;测试分两层——Jest 单元测试(pnpm run test)与 Cypress E2E(start:dev:test+test:e2e:open/test:e2e),E2E 必须使用:test构建以激活data-cypress-id属性;诊断有捷径——pnpm run analyze分析包体积,localStorage的debugLogging在生产环境即时开启调试日志。掌握这套体系后,无论是本地开发、编写测试还是排查线上问题,都能快速找到对应入口。
- 后端
- 前端
- 云原生
【免费下载链接】hedgedoc
HedgeDoc - Ideas grow better together
相关推荐
OpenMontage生产治理系统:质量门控与预算控制的实现原理
OpenMontage生产治理系统:质量门控与预算控制的实现原理 在当今AI视频制作领域,OpenMontage作为首个开源的智能视频生产系统,其 生产治理系统
人工智能AI Agent音视频媒体生成工作流自动化Arduino ESP32 安装三路径:10 分钟搞定 ESP32 开发环境配置完整指南
Arduino ESP32 安装三路径:10 分钟搞定 ESP32 开发环境配置完整指南 Arduino ESP32 是乐鑫官方的 Arduino 核心支持包,
嵌入式物联网驱动开发Tekton Pipelines 测试体系全解:单元测试、E2E、Conformance 与 Presubmit 实战指南
Tekton Pipelines 测试体系全解:单元测试、E2E、Conformance 与 Presubmit 实战指南 本文以 Tekton Pipelin
云原生CI/CDDevOps后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考