1. 执行摘要【Executive Summary】
- 目标:在保证可维护性与交付速度的前提下,确定企业级前端的通用技术栈、工程体系与治理策略,并给出落地路线图。
总体结论:
- 新建 SPA/中后台优先 Vite +(React 或 Vue);高并发/SEO/边缘渲染诉求明显时优先 Next.js 15(React 19) 或 Nuxt 3(Vue)。
- 数据密集型管理端推荐 AG Grid / TanStack Table 搭配 React Hook Form + Zod(或 Vue 对应方案)与 TanStack Query/SWR 做服务器状态管理。
- 构建工具优先 Vite;需与 webpack 生态高度兼容且追求构建性能时评估 Rspack;微前端首选 Module Federation 或 qiankun/single-spa 视存量系统而定。
- 质量保障采用 Vitest + Testing Library(单测/组件)+ Playwright(E2E),将 a11y 与 性能预算 纳入 CI。
- 监控与可观测性:OpenTelemetry(Trace/Metrics/Logs 标准化) + Sentry(前端错误/性能)。
2. 背景与业务约束
- 典型场景:中后台表格/表单密集、数据可视化、权限/审计、国际化、多团队协作、持续交付。
- 非功能需求:稳定性、可观测、可灰度、可回滚、性能(CWV 指标)、安全(XSS/依赖治理)。
3. 行业技术趋势【2024–2025】
- 框架与渲染:React 19 稳定,Next.js 15 稳定。服务端组件(RSC)、Server Actions 与边缘渲染成为常态化能力。
- Web 平台能力:CSS 容器查询、选择器 :has()、CSS Nesting 广泛可用;适配无栅格/卡片化布局更容易。
- 体验指标:INP 取代 FID 成为 Core Web Vitals 的交互性指标;与 LCP/CLS 一并成为常设目标。
- 工程化:Vite 生态占据主流;Rspack 以 Rust 实现,强调 webpack 兼容 + 高性能;Monorepo 倾向 Turborepo/Nx + pnpm。
4. 选型矩阵(按场景)
4.1 中后台(新建 SPA)
React 方案:
- UI:Ant Design 或 Arco Design
- 表格:AG Grid(社区版足够)或 TanStack Table(无头 + 高可定制)
- 表单:React Hook Form + Zod(类型安全校验)
- 数据:TanStack Query 或 SWR(服务端状态)
- 图表:Apache ECharts / AntV G2Plot
- 国际化与无障碍:i18next、axe-core
- 工具链:Vite、pnpm、ESLint+Prettier、Husky+lint-staged
- 测试:Vitest + Testing Library(组件)+ Playwright(E2E)
- 可观测性:OpenTelemetry + Sentry
Vue 方案:
- UI:Element Plus 或 Naive UI
- 表格:AG Grid / TanStack Table(Vue 适配)
- 表单:vee-validate 或 vue-hook-form(或配合 Zod)
- 其余同 React 方案等价替换
4.2 SSR/边缘渲染/SEO
- React:Next.js 15(App Router、RSC、Server Actions、Turbopack Dev)
- Vue:Nuxt 3(服务器渲染、文件路由、数据获取)
4.3 微前端/多团队并行
- 优先:Module Federation(Webpack/Rspack/Vite 插件)
- 存量系统:qiankun(基于 single-spa)或直接使用 single-spa 作为内核
- 适用:多技术栈共存、渐进改造、独立部署/灰度
4.4 数据可视化/大屏
- ECharts 为主,必要时接入 AntV 系列(G2Plot/G6/X6)
5. 基础设施与工程体系
5.1 运行时与包管理
- Node.js LTS(建议 20/22+),包管理优先 pnpm(工作区 + 硬链接节省磁盘)
5.2 Monorepo
- Turborepo 或 Nx,开启远程缓存;配合 Changesets 统一版本与变更日志。
5.3 构建与开发体验
- Vite(开发快、生态完备)
- Rspack(兼容 webpack loaders/plugins,适合存量迁移或极致构建性能场景)
- 产物:ESM 优先、可按需生成 modern/legacy 双产物(必要时)
5.4 CI/CD 基线
- 质量门禁:
typecheck
、lint
、test
、a11y
扫描、build
、bundle size
比对、e2e
冒烟 - 多环境:
dev
→staging
(含回归与金丝雀)→prod
;每个环境绑定独立监控指标与开关
6. 代码质量与测试策略
测试金字塔:
- 单元/组件:Vitest + Testing Library(优先以“用户视角”查询 DOM)
- 端到端:Playwright(多浏览器/移动端模拟)
- 可访问性:axe-core(CI 内静态扫描 + 关键流程 E2E 断言)
- 覆盖率目标:新增代码行覆盖 ≥ 80%,关键域模块函数覆盖 ≥ 90%
7. 性能与体验(Web Vitals 与预算)
核心指标目标(P75,移动/桌面分段):
- LCP ≤ 2.5s;INP ≤ 200ms;CLS ≤ 0.1
性能预算(建议起点):
- 首屏 JS(gzip)≤ 170–250 KB(按业务复杂度调整);首屏 CSS(gzip)≤ 50–100 KB
- 关键路径图片采用 AVIF/WebP + 响应式源集;图标优先 SVG
优化策略清单:
- RSC/Server Actions(SSR/边缘)减少客户端 JS;路由级/组件级代码拆分;
prefetch
/preload
- 表格虚拟化、惰性渲染;避免长任务,使用
scheduler
/requestIdleCallback
;必要时 Web Worker/OffscreenCanvas - 数据层缓存与失效策略(Stale-While-Revalidate);合理设置
cache-control
- RSC/Server Actions(SSR/边缘)减少客户端 JS;路由级/组件级代码拆分;
8. 安全与合规
- CSP(含
script-src 'nonce-...'
、strict-dynamic
) - Trusted Types(逐步开启/Report-Only → 强制)
- 依赖治理:锁定 registry、启用
pnpm audit
/SCA、禁止未备案三方脚本 - XSS/CSRF/点击劫持/子资源完整性(SRI)基线配置
9. 可观测性与稳定性
- OpenTelemetry JS:前端 Trace(与后端打通)、自定义事件、资源/网络指标
- Sentry:错误聚合、来源映射(Source Map 上传)、性能事务
- 关键流程埋点模型:登录/下单/导出/主操作路径;出问题可还原“用户故事”
10. 样例技术组合(可直接落地)
10.1 React 中后台(SPA)
Vite + React 19 + Ant Design + TanStack Query + RHF + Zod + ECharts + AG Grid + i18next + axe-core
Vitest + Testing Library + Playwright
;OpenTelemetry + Sentry
初始化建议:
# 创建项目
pnpm create vite@latest acme-admin --template react-ts
cd acme-admin && pnpm i
# 关键依赖
pnpm add antd @tanstack/react-query react-hook-form zod i18next react-i18next axios echarts ag-grid-community ag-grid-react
pnpm add -D @testing-library/react @testing-library/user-event vitest playwright axe-core eslint prettier husky lint-staged @types/node
# 脚本建议
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"typecheck": "tsc -b --pretty false",
"lint": "eslint .",
"test": "vitest run",
"e2e": "playwright test"
}
10.2 SSR/边缘(React)
Next.js 15 + React 19 + Ant Design + TanStack Query(或使用 Server Actions)
- 图片:Next Image;路由:App Router;部署:Vercel/自建边缘
10.3 Vue 中后台
Vite + Vue 3 + Element Plus/Naive UI + @tanstack/vue-query + vee-validate + Zod + ECharts + AG Grid
10.4 微前端
- Module Federation(Webpack/Rspack/Vite 插件):分域部署、共享依赖版本策略(严格 SemVer + Exposes/Remotes 规划)
- qiankun/single-spa:主/子应用路由隔离、样式沙箱、跨应用通信(全局状态/CustomEvent/URL)
11. 组织与治理
- 编码规范:TypeScript、ESLint、Prettier、Commitlint(Conventional Commits)
- 组件治理:Storybook(组件工作台)、设计令牌(Design Tokens)、样式主题化
- ADR(Architecture Decision Record):重大技术决策留痕(背景→方案→取舍→影响→回滚计划)
12. 风险识别与应对
- React 19/Next 15 升级风险:第三方库兼容性 → 先行 POC、灰度发布、双轨回滚
- 微前端复杂度:跨应用通信与依赖地狱 → 规范共享依赖与版本、限制造成全局副作用的库
- 构建链迁移(webpack → Vite/Rspack):自定义 loader/plugin 兼容性 → 梳理替代项与迁移脚本
- 性能回退:上线后 CWV 恶化 → 设定性能闸门 + 观察期回滚机制
13. 路线图(90 天)
- 0–2 周:需求与基线评估(现状盘点、性能与错误基线、依赖审计)
- 3–4 周:关键路径 POC(React/Vue + 表格/表单/图表 + SSR/边缘是否必要)
- 5–8 周:脚手架与工作流固化(Monorepo、CI/CD、质量门禁、模板仓库)
- 9–12 周:试点应用迁移与灰度(设定 SLO:错误率、CWV、发布频率、MTTR)
14. 附录:库清单(按域)
- UI:Ant Design、Arco Design、Element Plus、Naive UI
- 表格:AG Grid、TanStack Table
- 图表:Apache ECharts、AntV G2Plot
- 数据获取/状态:Redux Toolkit(含 RTK Query)、TanStack Query、SWR
- 表单/校验:React Hook Form、vee-validate、Zod、Yup
- 构建:Vite、Rspack、Webpack、Module Federation(@module-federation/*)
- 测试:Vitest、Testing Library、Playwright
- 国际化/a11y:i18next、axe-core
- 可观测性:OpenTelemetry JS、Sentry JS
- 工程:pnpm、Turborepo、Nx、Changesets、Storybook
15. 参考与模板
本节给出可直接落地的脚手架、规范与 CI 模板,以及 Module Federation 最小仓库拓扑示意,并附常见领域模板片段。
15.1 脚手架命令(可复制)
React 中后台(Vite)
pnpm create vite@latest acme-admin --template react-ts
cd acme-admin && pnpm i
Next.js 15(SSR/边缘渲染)
pnpm dlx create-next-app@latest acme-web \
--ts --eslint --app --src-dir --import-alias "@/*"
cd acme-web && pnpm i
Vue 3 中后台(Vite)
pnpm create vite@latest acme-console --template vue-ts
cd acme-console && pnpm i
Rspack(高性能打包 & 兼容 webpack 生态)
pnpm dlx create-rspack@latest acme-rspack
cd acme-rspack && pnpm i
Monorepo(Turborepo)
pnpm dlx create-turbo@latest acme-turbo -y
cd acme-turbo && pnpm i
Monorepo(Nx)
pnpm dlx create-nx-workspace@latest acme-nx --preset=apps --pm=pnpm
cd acme-nx && pnpm i
Vite + Module Federation(vite-plugin-federation)
pnpm add -D @originjs/vite-plugin-federation
15.2 代码规范与工程基线示例
tsconfig.base.json
(Monorepo 可复用)
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022", "DOM"],
"module": "ESNext",
"moduleResolution": "Bundler",
"jsx": "react-jsx",
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitOverride": true,
"resolveJsonModule": true,
"useDefineForClassFields": true,
"skipLibCheck": true,
"baseUrl": ".",
"paths": {"@/*": ["src/*"]}
}
}
.eslintrc.cjs
(React/TS)
module.exports = {
root: true,
env: { browser: true, es2022: true, node: true },
parser: "@typescript-eslint/parser",
parserOptions: { ecmaVersion: "latest", sourceType: "module" },
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"plugin:jsx-a11y/recommended",
"plugin:import/recommended",
"plugin:import/typescript",
"prettier"
],
settings: { react: { version: "detect" } },
plugins: ["@typescript-eslint", "react", "react-hooks", "jsx-a11y", "import"],
rules: {
"import/order": ["warn", { "newlines-between": "always", "alphabetize": {"order": "asc"} }],
"react/react-in-jsx-scope": "off",
"@typescript-eslint/consistent-type-imports": ["warn", {prefer: "type-imports"}]
}
}
.prettierrc
{ "singleQuote": true, "semi": false, "trailingComma": "all", "printWidth": 100 }
commitlint.config.cjs
module.exports = { extends: ["@commitlint/config-conventional"] }
package.json
(lint-staged + Husky)
{
"scripts": {
"prepare": "husky",
"lint": "eslint .",
"format": "prettier -w .",
"typecheck": "tsc -b --pretty false",
"test": "vitest run"
},
"lint-staged": {
"**/*.{ts,tsx,js,jsx}": ["eslint --fix"],
"**/*.{json,md,css,scss}": ["prettier -w"]
}
}
.editorconfig
root = true
[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
15.3 CI 样例
GitHub Actions:.github/workflows/ci.yml
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with: { version: 9 }
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
- name: Install deps
run: pnpm install --frozen-lockfile
- name: Typecheck
run: pnpm run typecheck
- name: Lint
run: pnpm run lint
- name: Unit tests
run: pnpm run test -- --coverage
- name: Build
run: pnpm run build
e2e:
needs: build-and-test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with: { version: 9 }
- uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
- name: Install
run: pnpm i
- name: Install Playwright Browsers
run: pnpm dlx playwright install --with-deps
- name: E2E
run: pnpm run e2e
GitLab CI:.gitlab-ci.yml
stages: [install, verify, build, e2e]
image: node:22-alpine
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .pnpm-store
- node_modules/
variables:
PNPM_HOME: /root/.local/share/pnpm
PLAYWRIGHT_BROWSERS_PATH: /ms-playwright
before_script:
- corepack enable
- pnpm -v
- pnpm config set store-dir .pnpm-store
install:
stage: install
script: pnpm i --frozen-lockfile
verify:
stage: verify
script:
- pnpm run typecheck
- pnpm run lint
- pnpm run test -- --coverage
build:
stage: build
script: pnpm run build
artifacts:
paths:
- dist
e2e:
stage: e2e
image: mcr.microsoft.com/playwright:v1.47.0-jammy
script:
- pnpm i --frozen-lockfile
- pnpm dlx playwright install --with-deps
- pnpm run e2e
15.4 Module Federation 最小仓库拓扑与示例
目录拓扑(Monorepo)
root/
├─ apps/
│ ├─ shell/ # 宿主应用(路由/导航/统一布局)
│ └─ users/ # 远程应用(示例:用户域)
├─ packages/
│ └─ ui/ # 共享 UI 组件包
├─ tsconfig.base.json
├─ pnpm-workspace.yaml
└─ turbo.json | nx.json
宿主(webpack)apps/shell/webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container
module.exports = {
// ...entry/output/devServer
plugins: [
new ModuleFederationPlugin({
name: 'shell',
remotes: { users: 'users@http://localhost:4001/remoteEntry.js' },
shared: { react: { singleton: true }, 'react-dom': { singleton: true } }
})
]
}
远程(webpack)apps/users/webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'users',
filename: 'remoteEntry.js',
exposes: { './UserCard': './src/UserCard.tsx' },
shared: { react: { singleton: true }, 'react-dom': { singleton: true } }
})
]
}
宿主使用远程
// apps/shell/src/App.tsx
// 声明模块:在 src/remote.d.ts 中加 declare module 'users/UserCard'
import UserCard from 'users/UserCard'
export default function App(){
return <UserCard id="42" />
}
Vite 方案(vite-plugin-federation)
// apps/shell/vite.config.ts
import federation from '@originjs/vite-plugin-federation'
export default {
plugins: [
federation({
name: 'shell',
remotes: { users: 'http://localhost:4001/assets/remoteEntry.js' },
shared: ['react', 'react-dom']
})
]
}
// apps/users/vite.config.ts
import federation from '@originjs/vite-plugin-federation'
export default {
plugins: [
federation({
name: 'users',
filename: 'remoteEntry.js',
exposes: { './UserCard': './src/UserCard.tsx' },
shared: ['react', 'react-dom']
})
]
}
启动端口约定
apps/shell: http://localhost:4000
apps/users: http://localhost:4001
15.5 版本与发布(Changesets)
安装与配置
pnpm add -D changesets
pnpm dlx changeset init
package.json
脚本
{
"scripts": {
"changeset": "changeset",
"version-packages": "changeset version",
"release": "pnpm build && changeset publish"
}
}
GitHub Actions(自动发版) .github/workflows/release.yml
name: Release
on:
push:
branches: [ main ]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with: { version: 9 }
- uses: actions/setup-node@v4
with:
node-version: 22
registry-url: 'https://registry.npmjs.org'
cache: 'pnpm'
- run: pnpm i --frozen-lockfile
- run: pnpm run version-packages
- run: pnpm run release
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
15.6 模板仓库结构(参考)
root/
├─ .github/
│ └─ workflows/ (ci.yml, release.yml)
├─ apps/ (shell, users, admin, web)
├─ packages/ (ui, config, eslint-config, tsconfig)
├─ e2e/ (Playwright 场景)
├─ .editorconfig .prettierrc .eslintrc.cjs commitlint.config.cjs
├─ tsconfig.base.json pnpm-workspace.yaml turbo.json | nx.json
└─ README.md ADRs/
15.7 安全与合规模板
CSP(Nginx 示例)
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'nonce-__NONCE__' 'strict-dynamic'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'self' https://api.example.com; frame-ancestors 'none'; base-uri 'self'" always;
Trusted Types(Report-Only → 强制)
Content-Security-Policy: require-trusted-types-for 'script'; report-uri https://csp-report.example.com
富文本渲染安全(DOMPurify)
import DOMPurify from 'dompurify'
export function SafeHTML({ html }: { html: string }) {
return <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(html) }} />
}
15.8 领域模板片段
网关鉴权(Axios 拦截器 + 刷新令牌)
import axios from 'axios'
let refreshing: Promise<string> | null = null
const api = axios.create({ baseURL: '/api' })
api.interceptors.request.use(cfg => {
const token = localStorage.getItem('access_token')
if (token) cfg.headers.Authorization = `Bearer ${token}`
return cfg
})
api.interceptors.response.use(r => r, async (err) => {
const { response, config } = err
if (response?.status === 401 && !config._retried) {
config._retried = true
refreshing ||= fetch('/auth/refresh', { method: 'POST' }).then(r => r.text())
const newToken = await refreshing.finally(() => (refreshing = null))
localStorage.setItem('access_token', newToken)
config.headers.Authorization = `Bearer ${newToken}`
return api(config)
}
return Promise.reject(err)
})
export default api
权限路由(RBAC)
// 假设用户角色从会话获取
export function canAccess(roles: string[], need: string[]) {
return need.every(r => roles.includes(r))
}
// React Router 示例
// <Route path="/admin" element={ canAccess(user.roles, ['admin']) ? <Admin/> : <NoAuth/> } />
CSV 导出(UTF-8 BOM 兼容 Excel)
export function exportCsv(name: string, rows: string[][]) {
const csv = '' + rows.map(r => r.map(v => `"${(v ?? '').toString().replace(/"/g,'""')}"`).join(',')).join('
')
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' })
const a = document.createElement('a')
a.href = URL.createObjectURL(blob)
a.download = `${name}.csv`
a.click()
URL.revokeObjectURL(a.href)
}
打印样式(隐藏非打印区)
@media print {
.no-print { display: none !important; }
body { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}
WYSIWYG 接入建议
- 富文本编辑器:TipTap / Quill / TinyMCE。上传路径、粘贴过滤、图片压缩需统一策略。
- 渲染端统一通过 DOMPurify 进行 sanitize;后端二次清洗 + 存储白名单。
低代码/可视化搭建接入(iframe + postMessage)
// 宿主监听
window.addEventListener('message', (e) => {
if (e.origin !== 'https://builder.example.com') return
const { type, payload } = e.data || {}
if (type === 'SAVE_SCHEMA') {
// TODO: 校验 + 存储
}
})
// 子应用发送
window.parent.postMessage({ type: 'READY' }, '*')