扣子罗盘(coze-loop)前端开发指南:基于 Rush.js Monorepo 的环境搭建、开发调试与构建实践

原创2026-10-11 20:29:011,911 阅读
文章标签:人工智能AI 应用AI Agent提示工程AI 评测可观测性LLMOps后端前端

扣子罗盘(coze-loop)前端开发指南:基于 Rush.js Monorepo 的环境搭建、开发调试与构建实践

本文面向希望在本地搭建 CozeLoop(扣子罗盘)前端开发环境的开发者,完整讲解基于 Rush.js 管理的 Monorepo 前端仓库从环境准备、依赖安装、开发调试到生产构建的全流程,并结合仓库内 frontend/apps/cozeloop 的源码与配置,深入说明 workspace 依赖机制、Rsbuild 构建管线、路由组织以及 API 类型生成等关键实现。读完本文,你将能够独立完成 CozeLoop 前端的本地启动、开发与构建,并理解其"源码即依赖"的 monorepo 协作方式。

一、前端仓库整体认知

CozeLoop 是一个下一代 AI Agent 优化平台,前端部分位于仓库根目录下的 frontend 目录,采用 Monorepo 架构,由 Rush.js 统一管理。整个前端被拆分为三类角色:

  • 应用入口:frontend/apps/cozeloop,即"扣子罗盘"主应用,是一个 React 应用;
  • 业务模块包:@cozeloop/* 系列,如账号(account)、提示词(prompt-pages)、评测(evaluate-pages)、可观测性(observation-pages)、标签(tag-pages)等;
  • 架构基础包:@coze-arch/* 系列,如设计系统(coze-design)、ESLint 配置、TypeScript 配置、Vitest 配置、构建配置等公共设施。

从 frontend/apps/cozeloop/README.md 可以确认应用的核心技术栈:React 18.2 + TypeScript 5.8、Rsbuild 构建、React Router 6.22 路由、Zustand 状态管理、Tailwind CSS 3.3 与 Less 样式、@coze-arch/coze-design 组件库,并内置 i18n 国际化能力。

二、环境要求与准备工作

原文档明确列出了三件套版本要求,这是保证构建产物一致性的关键,务必严格对齐:

依赖 版本要求 说明
Node.js 24+(推荐 lts/krypton) 运行时环境,必须满足版本下限
pnpm 10.27.0 包管理器,由 Rush 驱动
Rush 5.172.1(即 @microsoft/rush) Monorepo 任务编排器

2.1 安装 Node.js

推荐使用 nvm 安装并锁定 lts/krypton 版本:

nvm install lts/krypton
nvm alias default lts/krypton # 设置默认 Node 版本
nvm use lts/krypton

2.2 检出仓库并切换目录

# 克隆仓库
git clone git@github.com:coze-dev/coze-loop.git

# 切换目录
cd frontend

2.3 安装全局依赖

npm i -g pnpm@10.27.0 @microsoft/rush@5.172.1

之所以要全局安装指定版本的 pnpm 与 Rush,是因为 Rush 需要借助固定版本的 pnpm 来生成统一的依赖树与 lockfile,跨版本使用可能导致 pnpm-lock.yaml 不一致。

三、安装/更新项目依赖:rush update

进入 frontend 目录后,直接执行:

rush update

rush update 会读取 rush.json 中声明的所有项目(apps、packages),解析各包 package.json 中的 workspace:* 依赖关系,并在 common/config/subspaces/default/ 下生成统一的 pnpm-lock.yaml。这与直接在各子包中执行 pnpm install 的关键区别在于:整个 monorepo 只维护一份 lockfile 和一个 node_modules 拓扑,从而保证所有 workspace 包使用同一套依赖版本,避免"依赖地狱"。

四、启动开发服务器

扣子罗盘项目位于 apps/cozeloop 目录,文档特别强调:在 Rush 管理的项目中应使用 rushx 而不是 pnpm run 或 npm run,因为 rushx 由 Rush 注入正确的环境变量并在项目上下文内执行脚本。

cd apps/cozeloop

rushx dev

启动后在浏览器中打开 http://localhost:8090/](http://localhost:8090/) 即可查看页面。端口 8090 并非随意设定,而是定义在 [frontend/apps/cozeloop/rsbuild.config.ts 中:

const port = 8090;

export default createRsbuildConfig({
  server: {
    port,
    cors: { origin: '*' },
  },
  dev: {
    lazyCompilation: false,
    assetPrefix: `http://localhost:${port}`,
    client: { port: `${port}`, host: 'localhost', protocol: 'ws' },
  },
  html: {
    title: 'Coze Loop',
    template: './src/assets/template.html',
    favicon: './src/assets/images/coze.svg',
    crossorigin: 'anonymous',
  },
});

从配置可以看到:开发服务默认关闭 lazyCompilation、开启 CORS,并通过 assetPrefix 与 client 配置建立了基于 WebSocket 的 HMR 通道;HTML 模板与 favicon 分别指向 src/assets/template.html 与 src/assets/images/coze.svg。

4.1 不同环境/区域的启动变体

查看 frontend/apps/cozeloop/package.json 的 scripts 可以发现,rushx dev 实际是 npm run dev:cn-boe 的别名,完整的环境矩阵如下:

脚本 环境变量 用途
dev REGION=cn CUSTOM_VERSION=inhouse BUILD_TYPE=offline 默认开发(中国区 BOE 内网环境)
dev:cn REGION=cn 中国区开发
dev:cn-release REGION=cn CUSTOM_VERSION=release BUILD_TYPE=online 中国区生产联调
dev:base 无 纯 Rsbuild dev server

这些环境变量(REGION、CUSTOM_VERSION、BUILD_TYPE)贯穿构建与运行期,用于区分部署区域(cn/us/eu)、自定义版本(inhouse/release)以及构建类型(online/offline)。

五、生产构建:Rsbuild 管线

扣子罗盘项目由 Rsbuild 构建,构建命令为:

cd apps/cozeloop

rushx build

执行链路为 build → build:prod(cross-env REGION=cn rsbuild build)。此外还提供以下配套脚本:

  • build:ts:tsc -b tsconfig.build.json,TypeScript 类型检查与增量编译;
  • preview:rsbuild preview,本地预览构建产物;
  • analyze:cross-env RSDOCTOR=true rsbuild build,借助 Rsdoctor 插件分析构建包体积(对应 devDependencies 中的 @rsdoctor/rspack-plugin)。

六、workspace 依赖:源码即依赖

打开 frontend/apps/cozeloop/package.json,可以看到大量依赖以 workspace:* 版本声明:

"dependencies": {
  "@cozeloop/account": "workspace:*",
  "@cozeloop/api-schema": "workspace:*",
  "@cozeloop/auth-pages": "workspace:*",
  "@cozeloop/components": "workspace:*",
  "@cozeloop/evaluate-pages": "workspace:*",
  "@cozeloop/observation-pages": "workspace:*",
  "@cozeloop/prompt-pages": "workspace:*",
  "@cozeloop/tag-pages": "workspace:*",
  "react": "~18.2.0",
  "zustand": "^4.4.7"
}

这表示这些包全部在仓库内维护。扣子罗盘项目依赖的是这些 workspace 包的源码而非构建产物——直接修改 workspace 依赖的源代码,变更会立刻生效(有时候需要重新运行开发服务器)。这一机制让跨包联调无需先 build 再引用产物,极大提升了开发效率。

从 frontend/packages/loop-base 与 frontend/packages/loop-pages 的目录结构可以确认:account、api-schema、components、guard、i18n、stores、toolkit 等基础能力在 loop-base 下维护,而 auth-pages、prompt-pages、evaluate-pages、observation-pages、tag-pages 等页面模块在 loop-pages 下维护。

七、更新前端 API 类型:从 IDL 到 TypeScript

当后端接口变更时,前端需要重新生成 API 类型。原文档给出的命令是:

rush update-api

7.1 产物位置

文档中提及 IDL 相关文件将生成在 packages/cozeloop/api-schema,需要说明的是:在当前仓库中,@cozeloop/api-schema 包的实际路径为 frontend/packages/loop-base/api-schema(原文档路径已随仓库演进调整,请以仓库实际结构为准)。该包通过 package.json 的 exports 按领域暴露入口,例如:

"exports": {
  ".": "./src/index.ts",
  "./observation": "./src/api/observability/index.ts",
  "./evaluation": "./src/api/evaluation/index.ts",
  "./data": "./src/api/data/index.ts",
  "./llm-manage": "./src/api/llm-manage/index.ts",
  "./foundation": "./src/api/foundation/index.ts",
  "./prompt": "./src/api/prompt/index.ts"
}

7.2 IDL 生成管线

查看 frontend/packages/loop-base/api-schema/package.json 可以发现,API Schema 更新实际由三段脚本串联:

"prethrift": "bash ./scripts/download-thrift.sh --branch=main",
"thrift": "idl2ts gen ./",
"update": "npm run thrift"

即:先下载 IDL(thrift 文件),再由 @coze-arch/idl2ts-cli 生成 TypeScript 代码。

下载脚本 frontend/packages/loop-base/api-schema/scripts/download-thrift.sh 的实现非常巧妙:

  • 若检测到当前所在仓库就是 coze-dev/coze-loop,则直接软链接本地 idl/thrift 目录(位于仓库根目录 idl/thrift/coze/loop),保证本地开发时 IDL 与源码同步;
  • 否则通过 git sparse-checkout 从远程仓库浅克隆 idl/thrift 目录到 node_modules/.cache/coze-loop-idl/;
  • 默认分支为 main,可通过 --branch 参数指定其他分支。

随后 frontend/packages/loop-base/api-schema/api.config.js 定义 idl2ts 的生成规则,将 prompt、observability、evaluation、data、llm、foundation 等各领域的 thrift 文件分别映射为独立的 TS 模块,产物输出到 ./src/api/idl。例如:

entries: {
  promptDebug: './prompt/coze.loop.prompt.debug.thrift',
  promptManage: './prompt/coze.loop.prompt.manage.thrift',
  observabilityTrace: './observability/coze.loop.observability.trace.thrift',
  evaluationEvalSet: './evaluation/coze.loop.evaluation.eval_set.thrift',
  dataDataset: './data/coze.loop.data.dataset.thrift',
  foundationSpace: './foundation/coze.loop.foundation.space.thrift',
  // ...
}

从后端源码也可以印证这一链路:IDL 定义位于 idl/thrift/coze/loop,对应的 Go 服务端类型与处理逻辑由 backend/kitex_gen/coze/loop 和 backend/api/handler/coze/loop 承载,前后端以 thrift IDL 为唯一契约。

八、应用源码结构纵深

8.1 应用入口与启动流程

入口文件 frontend/apps/cozeloop/src/index.tsx 展示了应用启动前的异步初始化:

await Promise.all([
  initIntl({ fallbackLng: ['zh-CN', 'en-US'] }),
  pullFeatureFlags({ timeout: 1000 * 4, fetchFeatureGating: ... }),
  dynamicImportMdBoxStyle(),
]);

即并行完成国际化初始化(兜底语言为 zh-CN 与 en-US)、特性开关拉取(4 秒超时)以及 Markdown 盒子样式动态导入,随后挂载到 #cozeloop-root 节点。

8.2 应用组件树

frontend/apps/cozeloop/src/app.tsx 组装了应用骨架:

const router = createBrowserRouter(routeConfig);

export function App() {
  useSetupI18n();
  return (
    <CozeLoopProvider i18n={I18n} sendEvent={sendEvent}>
      <Suspense fallback={<PageLoading />}>
        <LocaleProvider>
          <RouterProvider router={router} />
        </LocaleProvider>
      </Suspense>
    </CozeLoopProvider>
  );
}

CozeLoopProvider 注入国际化与埋点(sendEvent 来自 @cozeloop/tea-adapter),配合 Suspense 支持业务模块的按需懒加载。

8.3 路由组织

frontend/apps/cozeloop/src/routes/index.tsx 定义了完整的路由树,清晰映射了平台的四大业务域:

路径 模块 说明
/auth/* @cozeloop/auth-pages 登录鉴权
/console/enterprise/:enterpriseID/space/:spaceID/pe/* @cozeloop/prompt-pages 提示工程(Prompt Engineering)
/console/.../space/:spaceID/evaluation/* @cozeloop/evaluate-pages 评测系统
/console/.../space/:spaceID/observation/* @cozeloop/observation-pages 可观测性
/console/.../space/:spaceID/tag/* @cozeloop/tag-pages 标签管理

所有业务页面均通过 lazy(() => import(...)) 懒加载,路由结构采用 enterprise → space → 业务域 的三级组织模型。

8.4 鉴权与空间初始化

frontend/apps/cozeloop/src/routes/base-route.tsx 负责登录态守卫:settling 时展示加载页、not_login 时重定向到 /auth/login、logined 时进入 GuardProvider 包裹的业务路由。

frontend/apps/cozeloop/src/hooks/use-setup-space.ts 则处理 Space(空间)的选择逻辑:拉取用户空间列表后,优先匹配 URL 中的 spaceID,否则回退到 Personal 类型空间或列表首个空间,并自动重定向到正确的 /console/enterprise/:id/space/:spaceId 路径;找不到空间时返回 NOT_FOUND,请求失败时返回 FETCH_ERROR,两者分别由 frontend/apps/cozeloop/src/components/basic-layout/index.tsx 渲染对应的错误页。

8.5 样式与 UI 设施

  • Tailwind 配置:frontend/apps/cozeloop/tailwind.config.ts 基于 @cozeloop/tailwind-config 工厂函数生成,content 扫描范围覆盖 coze-design、components 及各业务包,确保跨包类名都能被正确提取;
  • 基础布局:frontend/apps/cozeloop/src/components 下提供 basic-layout(基础布局)、navbar(导航栏)、breadcrumb(面包屑)、user-info-section(用户信息区)与 locale-provider(语言环境提供者)等通用组件;
  • API 错误提示:frontend/apps/cozeloop/src/hooks/use-api-error-toast.tsx 监听 @cozeloop/api-schema 暴露的 $notification 的 apiError 事件,统一以 Toast 形式呈现接口异常。

九、测试与质量保障

此外,frontend/apps/cozeloop/config/rush-project.json 向 Rush 声明了 build 与 ts-check 操作的输出目录(dist、lib-ts、src/locales),使 Rush 能够精确跟踪构建产物并支持增量构建。

十、常见问题与排查建议

  • rushx 提示找不到命令:请确认已按本文第二节全局安装 @microsoft/rush@5.172.1,且在当前项目目录(apps/cozeloop)下执行;
  • 依赖不一致 / lockfile 冲突:重新执行 rush update 以对齐 common/config/subspaces/default/pnpm-lock.yaml;
  • 端口被占用:8090 由 rsbuild.config.ts 固定,如需调整请修改 frontend/apps/cozeloop/rsbuild.config.ts 中的 port 常量;
  • API 类型与后端不同步:修改 workspace 依赖源码后需重跑开发服务器,若涉及 API 类型变更,则在 frontend/packages/loop-base/api-schema 目录执行 rushx update(或仓库级 rush update-api)重新生成。

十一、许可证

前端代码与整个仓库一致,采用 Apache License, Version 2.0 开源协议。

登录后查看全文
coze-loop