Oxide Web Console
Oxide API] 的 Web 客户端。

实时演示
在 https://console-preview.oxide.computer 上,控制台作为一个静态站点部署,并运行一个位于 Service Worker 中的模拟 API。您可以创建模拟资源,它们会在客户端导航之间持久化,但仅存在于浏览器中:其他人无法看到它们,且模拟“DB”会在页面加载时重置。模拟 API 中的请求和响应体与 Oxide API 的 OpenAPI 规范 相匹配,但行为仅在开发和控制台测试所需的详细程度上进行模拟,并不能完全代表真实 API。
目标与原则
- 控制台不是一个应用程序,它是应用程序(Oxide API)的 客户端 —— 最小化客户端状态
- 作为 API 的透明视图 —— 教授 API 概念,避免让用户学习任何控制台特定的内容
- 简单、可预测且广泛可用优于在少数地方深度打磨
- 当我们没有产品清晰度时,构建最简单的东西并继续前进
- 堆栈的其他地方存在足够的技术风险,因此保持保守:
- 专注于构建我们确定需要的东西
- 依赖好的库,并以它们希望被使用的方式使用它们
- 基于糟糕的抽象进行构建成本高昂 —— 在确定正确的抽象之前,重复是可以接受的
- 可链接性 —— 使用路由来捕获应用状态
- 依赖从 API 规范生成的代码以确保正确性
架构
为了避免服务端渲染(以及在机架上运行 JS)的复杂性,Web 控制台是一个完全基于客户端的 React 应用。我们使用 Vite(在生产构建中内部使用 Rollup)来构建一组资源(index.html、JS 包、CSS、字体、图像),并从 Nexus 中一组特殊的控制台端点将这些资源作为静态文件提供服务。从控制平面 API 服务器的角度来看,Web 控制台仅仅是:
- 一个静态资源目录和一些提供这些资源的端点
- 一些用于处理登录/登出等身份验证操作的其他端点
- 一个会话表(实际上专用于控制台,但本质上并非如此)
Web 控制台作为 API 消费者没有特殊权限。登录时会设置一个 cookie,之后我们使用基于 cookie 的身份验证进行 API 请求。有关更详细的讨论,请参阅 RFD 223 Web Console Architecture。这些端点位于 Omicron 中的 nexus/src/external_api/console_api.rs。
技术
- TypeScript + React(+ React Router、TanStack Query、TanStack Table)
- Vite 用于开发服务器和浏览器打包
- Tailwind 用于样式
- oxide.ts 从 Nexus 的 OpenAPI 规范 生成 API 客户端
- 测试
- Mock Service Worker 用于模拟 API 服务器
- Vitest 用于单元测试
- Playwright 用于 E2E 浏览器测试
目录结构
该应用位于 app。你可以在 app/routes.tsx 中查看路由结构。同样在 app 中,我们有一个 ui 目录,其中存放着底层组件,以及一个 api 目录,用于存放生成的 API 客户端及其 React Query 封装。后者在 tsconfig.json 中设置了别名,以便从主应用中作为 @oxide/api 轻松导入。
开发
Node.js 版本
使用 Node.js v18+。
安装依赖
npm install
npx playwright install # only needed to run e2e tests
运行 Vite 开发服务器 + MSW 模拟 API
这是我们进行大多数控制台开发的方式。只需运行:
npm run dev
并在浏览器中导航到 http://localhost:4000。当您编写源文件时,正在运行的应用程序会自动更新。此模式使用 Mock Service Worker 在浏览器中运行模拟 API。此模拟 API 也用于测试。
指定非默认用户
从 mock-api/user.ts 中的用户列表中选择一个用户。没有舰队查看器权限的是 Hans Jonas。打开浏览器控制台并运行:
document.cookie = 'msw-user=Hans Jonas;domain=localhost;path=/'
你现在是用户 Hans Jonas。若要返回默认状态,请删除该 cookie。(我们很快会实现通过 mock API 在登出时为你清除 cookie。)
针对本地 Nexus API 运行 Vite 开发服务器
你也可以在本地运行控制台开发服务器,同时关闭 mock 服务器,改为将请求转发至 localhost:12220。运行 npm run start:nexus 并在浏览器中导航至 http://localhost:4000/login/test-suite-silo/local。除非 Nexus 正在 localhost:12220 上运行,否则无法正常工作,而这是 omicron-dev 的默认设置(请参阅 Running Omicron (Simulated) 了解如何设置)。
运行所有组件的一种方式是使用 tools/start_api.sh 脚本,该脚本使用 tmux 在不同窗格中运行多个进程,并自动填充一些假数据(请参阅 tools/populate_omicron_data.sh 以查看具体内容)。从 omicron 目录中,运行 tools/start_api.sh。由于我们假设 console 和 omicron 位于相邻位置,其形式如下:
../console/tools/start_api.sh
针对 dogfood rack 运行本地开发服务器
- Get on the VPN
- Run
npm run start:dogfood - Go to https://localhost:4000 (note the https). The page won't work yet, and you'll get redirected to
/login, which will look like a 404 - Go to https://oxide.sys.rack2.eng.oxide.computer in another tab and log in
- Open the dev tools Storage tab and copy the
sessioncookie value, which should look liked9b1a96e151092eb0ea08b1a0d8c4788441f1894 - Go back to your localhost tab, open the developer console, and run
document.cookie = 'session=d9b1a96e151092eb0ea08b1a0d8c4788441f1894;domain=localhost;path=/'
再次访问 https://localhost:4000,您应该已经登录。
使用 Playwright 进行 E2E 测试
Playwright 测试位于 test/e2e。npm run e2e 在 Chrome、Firefox 和 Safari 中运行测试,但在本地开发中很少需要这样做。npm run e2ec 是 playwright test --project=chrome 的快捷方式,后者仅在 Chrome 中运行测试(速度最快,适用于本地开发)。Playwright 具有出色的 UI 模式,可用于运行和调试测试,您可以通过运行 npm run e2e -- --ui 来访问该模式。
要调试 CI 上的端到端失败,请检出包含失败的分支并运行 ./tools/debug-ci-e2e-fail.sh。它将下载来自 CI 的最新失败记录,并允许您打开失败的 playwright trace。
常用命令摘要
| Command | Description |
|---|---|
npm run dev | 运行带有 mock API 的 Vite 开发服务器 |
npm test | Vitest 单元测试 |
npm run e2ec | 仅在 Chrome 中运行 Playwright E2E 测试 |
npm run lint | ESLint |
npm run tsc | 检查类型 |
npm run ci | 执行 Lint、测试(单元测试和 e2e)以及类型检查 |
npm run fmt | 格式化所有内容。得益于编辑器集成,很少需要 |
npm run gen-api | 生成 API 客户端(参见 docs/update-pinned-api.md) |
npm run start:mock-api | 在端口 12220 上提供 mock API |