news 2026/9/28 2:23:17

HedgeDoc 前端开发实战指南:环境变量、单元/E2E 测试体系与生产调试

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HedgeDoc 前端开发实战指南:环境变量、单元/E2E 测试体系与生产调试
  • 后端
  • 前端
  • 云原生

【免费下载链接】hedgedoc

HedgeDoc - Ideas grow better together

项目地址:https://gitcode.com/gh_mirrors/he/hedgedoc
点击查看免费下载

本文基于 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_APItrue、false激活模拟后端(mocked backend)
NEXT_PUBLIC_TEST_MODEtrue、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→isTestMode
  • NEXT_PUBLIC_USE_MOCK_API→isMockMode
  • NODE_ENV === 'development'→isDevMode
  • ANALYZE→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:devnext 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等,覆盖了文档标题、文件上传、权限等真实用户场景)。

官方推荐的标准流程如下:

  1. 以测试模式启动前端(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 抓取元素。

  2. 打开 Cypress 测试加载器:

    pnpm run test:e2e:open
  3. 选择浏览器并运行测试套件。

如需在无头(headless)浏览器中运行全部测试:

pnpm run test:e2e

Cypress 配置见 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

项目地址:https://gitcode.com/gh_mirrors/he/hedgedoc
点击查看免费下载

相关推荐

上一篇:如何使用Percollate与Puppeteer:打造完美的网页转PDF解决方案
下一篇:如何看懂React Doctor诊断报告?0-100健康评分与错误分级完全指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 2:19:22

诗风秦韵诗词学习话廊“1+7管理模式”

1个理念,7个步骤。 1个理念:1、培养一群善于解决问题的组员,而不是自己去解决所有问题。 7个步骤:1、创建舒服的创作环境,让组员有更好的积极性、创造性去解决问题。2.调节组员的情绪,让组员从积极的角度看…

作者头像 李华
网站建设 2026/9/28 2:16:04

STM32开发参考方案全梳理:从环境搭建到资料平台,避开常见坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/28 2:15:42

真实废弃物九分类数据集实战:从4800张图到可训练管线

简介:本资源为面向计算机视觉初学者与图像分类实践者的真实废弃物图像分类数据集,覆盖纸板、食品有机物、玻璃、金属、杂项垃圾、纸张、塑料、纺织品垃圾和植被共9个类别,适合用于分类网络训练、迁移学习验证及垃圾分类相关课程设计。数据已完…

作者头像 李华
网站建设 2026/9/28 2:15:30

【PyQt】PyQt5基础组件:表格视图

表格视图作为应用程序中处理和展示数据的核心组件,尤其在处理大规模数据时,发挥着不可或缺的作用。在PyQt框架中,QTableView 提供了一个高效、灵活的方式来显示表格数据。通过结合模型-视图框架,可以将数据从模型中提取并呈现出来,确保仅加载当前可见的部分,提升了处理大…

作者头像 李华
网站建设 2026/9/28 2:15:14

【PyQt】PyQt5基础组件:窗口

在图形用户界面(GUI)开发中,PyQt作为Python语言中的一个重要工具包,提供了丰富的功能和灵活的用户界面定制能力。基于Qt框架,PyQt简化了开发者创建跨平台应用程序的过程。在实际开发过程中,创建窗口是每个PyQt应用程序的核心组成部分,它是用户与程序进行交互的起点。 通…

作者头像 李华