Day 16 / 共 20 天 · 第 4 周 前端/部署

前端技术栈

第 4 周切到前端。今天先认识这套 React 应用的"骨架":用什么框架、什么 UI 库、怎么构建、应用怎么启动。零基础也能跟——每个术语都配大白话。

📍 你在整门课的位置 · 第 4 周 前端/部署(Day 16-20,最后一周)
D16 前端技术栈 D17 前端结构 D18 动态表单 D19 部署 D20 收官串讲
L01

ice.js 3 + React 18

🤔 痛点:光有 React 还差得远 React 只解决"把数据变成界面"这一件事。可一个真实后台还要:路由(哪个 URL 显示哪页)、构建打包、数据管理、国际化……全自己搭一遍太累。
💡 本质:React 是发动机,ice.js 是整车 React = 发动机(造 UI 的核心库);ice.js(icejs 3)= 在发动机之上装好底盘、变速箱、方向盘的整车——路由、构建、数据流都配好了,还送你"约定式路由":在 pages/ 建个文件夹就自动变成一个页面路由,不用手写路由表。
📝 举个例子(约定式路由)frontend/src/pages/ 下新建目录 route/ 并放个 index.tsx → 访问 /route 就自动渲染这个页面,无需在任何路由表里登记。目录结构 = 路由结构。
⚠️ 常见误解:以为 ice.js 是"另一个和 React 二选一的框架"。其实它建在 React 之上——你写的仍是 React 组件,ice.js 只是把周边工程能力打包好了。

frontend/package.jsonreact ^18.2.0:23)、@ice/runtime ^1.0.0:16)、@ice/app ^3.0.0:35)。这是阿里的 ice.js 3(icejs)——基于 React 的应用框架,约定式路由 + 数据流。

React 和 ice.js 是什么关系? React 是"造 UI 的库"(把数据变成界面)。但只有 React 还不够——还要路由、构建、数据管理。ice.js 是在 React 之上的"全家桶框架",帮你把这些配好,还提供"约定式路由"(在 pages/ 建个文件夹就自动成为一个页面路由,不用手写路由表)。好比 React 是发动机,ice.js 是整车。
L02

antd + Pro 组件

UI 库是 Ant Design 4antd ^4.24.0:12),外加 Ant Design Pro 组件族:@ant-design/pro-components / pro-layout / pro-table / pro-form:6-9),图表 @ant-design/charts。HTTP 用 axios ^1.2.1

读法:antd 提供现成的按钮/表格/表单/弹窗等组件,不用自己写 CSS。Pro 组件是"企业级增强版"(带分页、筛选的高级表格 ProTable、带布局的 ProLayout),管理后台用它开发极快。还有 monaco-editor(VS Code 同款代码编辑器,用于插件 YAML 编辑)、js-yaml、react-markdown(渲染插件 README)。
L03

构建配置 + 开发代理

👶 小白 vs 👨‍🏫 老师 👶:本地前端为什么不能直接调线上后端,非得配个"代理"?
👨‍🏫:浏览器有"同源策略"——前端跑在 localhost:3000,直接请求 demo.higress.io 会被跨域拦截。
👶:那代理怎么绕过?
👨‍🏫:让 ice 的开发服务器当"中转站":前端把 /api/* 发给自己(同源,不跨域),ice 再替你转发demo.higress.io。好比你不方便直收国际快递,就先寄到一个国内转寄点。pathRewrite 负责把 /api 前缀去掉再转发。

frontend/ice.config.mts

ssr: false, ssg: false        // :10-12 纯 CSR 单页应用(SPA)
proxy: {                       // :16-22 开发代理
  '/api': { target: 'http://demo.higress.io/', changeOrigin: true,
            pathRewrite: { '^/api': '' } }
}
"开发代理"解决什么? 本地开发时前端跑在你电脑上(比如 localhost:3000),但后端 API 在别处。浏览器有"跨域"限制,前端不能直接调别的域名。开发代理让 ice 把 /api 开头的请求转发demo.higress.io——于是本地前端能直接用线上 demo 的后端调试,省去自己搭后端。pathRewrite/api 前缀去掉再转发。
L04

Monaco 本地托管

ice.config.mts:28-43copy-webpack-pluginnode_modules/monaco-editor/min/vs 拷到构建产物的 vs/ 目录。

读法:Monaco 编辑器需要一批 worker 资源文件。默认它会从 CDN 加载,但企业内网可能访问不了 CDN——所以把这些文件拷进自己的产物本地托管,离线也能用。这呼应了后端"一切自包含、单 jar 部署"的思路。
L05

app.ts 应用配置

打开应用 getUserInfo() getConfigs() getSystemInfo() dataLoader 并发拉三份(任一失败降级为空) 全局 storeuser/config/system 界面渲染
启动闭环:dataLoader 在渲染前并发拉三份数据 → 注入全局 store → 界面首帧就有数据,不闪空白。

frontend/src/app.ts 是 ice 的应用入口:

// :39-66 dataLoader:启动前并发拉三份数据
getUserInfo() / getConfigs() / getSystemInfo()   // 任一失败降级为空对象
// :14-22 authConfig:按 userInfo.type 生成 admin/user 权限位
// :24-37 storeConfig:把 dataLoader 结果注入全局 store 初始状态
dataLoader 是什么? 应用一打开,还没渲染界面前,就先并发拉取"当前用户是谁、系统配置、系统信息"三份数据。这样界面首次渲染就有数据可用,不会闪一下空白再加载。"任一失败降级为空对象"保证某个接口挂了也不至于整个应用打不开——健壮性设计。
L06

全局 store

frontend/src/store.ts:6-10 由三个 model 组成:user / config / systemcreateStore)。每个 model 是 ice 的 createModel(rematch 风格 state + reducers),如 models/config.ts:8-17

"全局 store"是干嘛的? 很多页面都要用到"当前用户""系统配置"这些数据。与其每个页面各自去请求,不如放进一个全局的"数据仓库"(store),所有页面共享读取。某处改了数据,用到它的界面自动更新。这就是"状态管理"——React 生态里非常核心的概念,这里用 ice 内置的 store 实现。
L07

i18n 国际化

frontend/src/i18n.ts:8-26:用 i18next,fallback zh-CN,内置 en/zh 两份 translation.jsonsrc/locales/{zh-CN,en-US}/translation.json)。package.json 还有 check-i18n 脚本校验中英文键一致。

读法:界面文案不写死,而是用 t('key') 取翻译。这套前端 i18n 和 Day 12 后端插件的 x-*-i18n 约定配合——插件的多语言标题由后端按语言返回,界面文案由前端 i18next 翻译,两条线共同实现全站中英文。
L08

今日小结 + 动手

🧠 今天你应该能回答

  • React 和 ice.js 的关系?什么是"约定式路由"?
  • 用了哪个 UI 库?Pro 组件是什么?
  • 开发代理解决什么问题?为什么 Monaco 要本地托管?
  • dataLoader 和全局 store 各自的作用?

✋ 动手

cd /Users/bitmart/work/codes/github/higress-group/higress-console/frontend
sed -n '1,70p' package.json
sed -n '1,43p' ice.config.mts
sed -n '14,66p' src/app.ts
cat src/store.ts
明天预告 · Day 17前端结构与页面——目录布局、ProLayout 菜单、路由定义 _defaultProps、API 层 request.tsx 拦截器,以及精读路由管理页的 CRUD。
← Day 15 Day 17 · 前端结构 →