← 返回场景决策

🔧 前端工程化与安全场景决策

什么时候用 / 什么时候不用 / 边界在哪里 — 9 大核心场景全解析

Monorepo 微前端 Vite vs Webpack CI/CD 自动化测试 XSS CSRF CSP Git规范

1. Monorepo vs 多仓库 — 代码组织决策

Monorepo = 大公司一栋楼 所有部门在同一栋楼,串门方便,共享设施
多仓库 = 各公司各买各的楼 独立自主,但串门要跑很远
什么时候用 Monorepo
  • 共享组件库:UI 组件、工具函数、类型定义 — 改一处所有项目同步
  • 全栈同一仓库:前端 + 后端 + 共享类型 — 一次 PR 改前后端
  • 多人协作频繁:团队 5-20 人,模块间依赖多 — 统一版本管理
  • 原子化提交:前后端接口变更一起提交 — 不出现版本不同步
什么时候用多仓库
  • 团队独立:不同团队完全独立开发 — 各自有自己的节奏
  • 代码敏感:核心算法/商业机密 — 不能和普通项目放一起
  • 部署独立:不同客户不同部署 — 权限隔离
  • 仓库过大:100+ 项目/GB级代码 — Monorepo 工具链压力大

📊 Monorepo vs 多仓库决策表

维度Monorepo多仓库 (Polyrepo)
代码共享✅ 极方便需要发包
原子提交✅ 一次PR全改多次PR+版本协调
构建速度需要增量构建独立构建快
权限控制粗粒度细粒度
CI 复杂度高(影响范围分析)
适合团队规模5-50人不限
工具pnpm workspace / Turborepo / Nx各自为政

💻 pnpm workspace Monorepo 配置

📀 monorepo
📁 apps/
web/
admin/
📁 packages/
ui/
pnpm-workspace.yaml
// pnpm-workspace.yaml packages: - 'apps/*' // 前端应用 - 'packages/*' // 共享库 // 目录结构 // ├── apps/ // │ ├── web/ → 前端项目 (Vue 3 + Vite) // │ └── admin/ → 管理后台 // ├── packages/ // │ ├── ui/ → 共享 UI 组件库 // │ ├── utils/ → 工具函数 // │ └── types/ → 共享 TypeScript 类型 // └── pnpm-workspace.yaml // apps/web/package.json 引用本地包 { "dependencies": { "@mylib/ui": "workspace:*", "@mylib/utils": "workspace:*" } }
面试金句 pnpm workspace 通过 workspace:* 协议实现本地包引用——符号链接(symlink)而非复制文件,修改 packages/utils 的代码,apps/web 立即生效无需发包。pnpm 的硬链接机制使 node_modules 节省大量磁盘空间(同版本依赖全局存储,各项目硬链接引用)。

2. 微前端 — 大型应用拆分决策

微前端 = 美食广场 每个档口独立经营(独立技术栈),顾客统一消费
单体前端 = 一个大工程 所有功能在一个代码库,统一管理但项目大了难以维护
什么时候用微前端
  • 巨石应用拆分:100+ 页面的后台系统 — 团队各自负责一个子应用
  • 技术栈混合:老系统 jQuery + 新系统 Vue — 渐进式迁移
  • 独立部署:各团队独立发布 — 不用等所有团队
  • 多团队并行:10+ 前端团队 — 各自为政互不干扰
什么时候不用微前端
  • 小项目:< 30 个页面 — 杀鸡用牛刀,增加大量复杂度
  • 同技术栈团队 < 5 人:不需要拆分 — 一个仓库就够
  • 强交互场景:跨子应用的拖拽、动画 — 微前端边界是性能和体验的坑
  • SEO 要求高:微前端不利于 SEO — 子应用内容爬虫可能看不到

📊 微前端方案决策表

方案原理JS沙箱样式隔离推荐度
qiankunHTML Entry + Proxy 沙箱✅ JS沙箱✅ Shadow DOM⭐⭐⭐
Module FederationWebpack 5 模块共享⭐⭐
single-spa路由劫持⭐⭐
iframe浏览器原生隔离✅ 完全隔离✅ 完全隔离⭐ 兼容性差

3. Vite vs Webpack — 构建工具决策

Vite = 高铁 按需加载,开发秒启动
Webpack = 公交车 每站都停,全量编译,稳但慢

📊 Vite vs Webpack 决策表

维度ViteWebpack
开发启动毫秒级(ESM)几十秒起(全量打包)
HMR 热更新毫秒级秒级
构建原理开发时 ESM + 生产时 Rollup全量打包
生态/插件丰富但不如 Webpack最丰富
配置复杂度极简复杂
CSS 预处理✅ 开箱即用需要 loader 链
Vue 支持官方推荐需要 vue-loader
兼容性ESM 浏览器IE11(旧版)
推荐度⭐⭐⭐ 新项目首选维护旧项目
⚠️ 选型建议:2024+ 新项目一律用 Vite。旧 Webpack 项目如果运行良好不要迁移,改构建工具性价比低。

4. CI/CD — 持续集成与部署决策

CI = 流水线质检 每件产品出厂前自动检测
CD = 快递自动发货 质检通过自动发货,不用人工打包
什么时候需要 CI/CD
  • 团队协作:2+ 人开发 — 自动跑 lint/test,防止低级错误合入
  • 频繁发布:每天/每周发布 — 自动化构建部署
  • 多环境:dev/staging/prod — 自动部署到对应环境
  • 质量保障:PR 合入前自动跑测试 — 不通过不准合

📊 CI/CD 方案决策表

工具托管适合价格
GitHub ActionsGitHub开源项目 + GitHub 生态免费额度大
GitLab CIGitLab私有部署 + 内网自建免费
Jenkins自建复杂流水线 + 大团队免费
VercelSaaS前端项目极速部署免费额度

💻 GitHub Actions 配置示例

📀 cicd-pipeline
📁 .github/workflows/
ci.yml
deploy.yml
📁 src/
# .github/workflows/ci.yml name: CI on: pull_request: branches: [main] push: branches: [main] jobs: build-and-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v2 with: { version: 8 } - uses: actions/setup-node@v4 with: { node-version: 20, cache: 'pnpm' } - run: pnpm install - run: pnpm lint # 代码规范检查 - run: pnpm test # 单元测试 - run: pnpm build # 构建验证
面试金句 GitHub Actions 的 cache: pnpm 缓存 node_modules,将安装时间从 60s+ 降至 5s。CI 流水线标准四步:lint(代码规范)→ test(单元测试)→ build(构建验证)→ deploy(部署)。PR 合入前必须 CI 全绿,防止主分支被破坏。

5. 自动化测试 — 测试策略决策

测试金字塔 = 饮食金字塔 底层多(单元测试),顶层少(E2E),健康均衡

📊 测试类型决策表

类型范围速度维护成本覆盖场景推荐比例
单元测试函数/组件毫秒工具函数、计算逻辑70%
集成测试模块交互秒级组件 + Store + API20%
E2E 测试完整流程分钟级关键业务流程10%
什么必须测试
  • 核心业务逻辑:价格计算、折扣规则、支付流程 — 错了就是钱
  • 工具函数:日期格式化、数据转换 — 纯函数最好测
  • API 层:接口参数、错误处理 — 防止接口变更漏改
什么不必测试
  • 第三方库本身:不要测 Vue 的响应式 — 人家自己有测试
  • 纯 UI 展示:颜色、字体大小 — 视觉回归测试更合适
  • 简单 CRUD:增删改查如果没特殊逻辑 — ROI 低

💻 Vitest 单元测试示例

📀 frontend-app
📁 src/utils/
price.test.ts
price.ts
date.test.ts
// utils/price.test.ts import { describe, it, expect } from 'vitest'; import { calcDiscount } from './price'; describe('calcDiscount', () => { it('正常折扣', () => { expect(calcDiscount(100, 0.8)).toBe(80); }); it('折扣为0时返回0', () => { expect(calcDiscount(100, 0)).toBe(0); }); it('负数价格抛错', () => { expect(() => calcDiscount(-1, 0.8)).toThrow(); }); });
面试金句 Vitest 是 Vite 原生测试框架,与 Vite 共享配置和转换管线(Jest 需要独立配置)。测试金字塔原则:70% 单元测试(快、维护低)+ 20% 集成测试 + 10% E2E。纯函数(无副作用)是最好测试的——输入确定输出,不需要 mock。

6. XSS 防御 — 跨站脚本攻击

XSS = 在你家里贴假通知 坏人把恶意脚本混在正常内容里,浏览器傻傻执行
⚠️ XSS 三种类型
  • 存储型 XSS:恶意代码存入数据库 → 所有用户浏览时执行 — 最危险
  • 反射型 XSS:恶意代码在URL参数中 → 点击链接时执行 — 钓鱼常用
  • DOM型 XSS:前端 JS 直接操作 DOM 插入恶意代码 — 不经过服务器
XSS 防御方案
  • 输入转义:所有用户输入展示前转义 < > & " ' — 最基本
  • v-html 禁用:Vue 中不用 v-html,用 {{ }} 自动转义 — 除非信任内容
  • Content-Security-Policy:限制脚本来源 — 只允许自己域名的脚本
  • HttpOnly Cookie:JS 读取不到 Cookie — 即使 XSS 也偷不到
  • DOMPurify:需要渲染 HTML 时用 DOMPurify 清洗 — 白名单过滤

💻 XSS 防御代码

📀 security
📁 src/
xss-defense.js
sanitizer.js
📁 backend/
SecurityConfig.java
// 1. Vue 中自动转义(默认安全) // ✅ {{ userInput }} — 自动转义 // ❌ v-html="userInput" — 危险! // 2. 必须渲染HTML时用 DOMPurify import DOMPurify from 'dompurify'; const safeHTML = DOMPurify.sanitize(userRichText); // 过滤掉 <script>、onerror 等,保留安全的 HTML 标签 // 3. URL 参数转义 const safeURL = encodeURIComponent(userInput); // 4. Spring Boot 后端转义 // 依赖: org.unbescape:unbescape String safe = HtmlEscape.escapeHtml4(userInput); // 5. Cookie 设置 HttpOnly // Spring Boot @Bean public CookieSerializer cookieSerializer() { DefaultCookieSerializer s = new DefaultCookieSerializer(); s.setCookieHttpOnly(true); // JS 无法读取 return s; }
面试金句 XSS 防御分层:① Vue {{ }} / React {} 自动 HTML 转义(默认安全);② 需要渲染富文本时用 DOMPurify.sanitize() 白名单过滤(保留安全标签,移除 script/onerror);③ HttpOnly Cookie 防止 JS 读取 Cookie(即使 XSS 也偷不到会话凭证);④ CSP 限制脚本来源。永远不要用 v-html 渲染用户输入

7. CSRF 防御 — 跨站请求伪造

CSRF = 有人冒充你签字 你在A站登录了,坏人诱骗你访问B站,B站偷偷发请求给A站
CSRF 防御方案
  • CSRF Token:每次请求带随机 Token — 服务器验证 Token 一致性
  • SameSite Cookie:Set-Cookie: SameSite=Strict — 跨站请求不带 Cookie
  • 验证 Referer/Origin:检查请求来源 — 简单但不完全可靠
  • JWT + Authorization Header:Token 放 Header 不是 Cookie — 天然防 CSRF

📊 CSRF 防御方案决策表

方案原理Cookie认证Token认证推荐度
CSRF Token表单/请求头带随机数✅ 必须不需要⭐⭐⭐
SameSite Cookie浏览器不发送跨站Cookie✅ 简单不需要⭐⭐⭐
Referer 检查验证请求来源辅助不需要⭐⭐
用 Token 认证不用 Cookie-天然免疫⭐⭐⭐

💻 Spring Security CSRF 配置

📀 backend-service
📁 src/main/java/.../config/
SecurityConfig.java
WebConfig.java
📁 frontend/src/
axios.js
// Spring Security 默认开启 CSRF // 表单提交时需要带 _csrf 参数 // 前端 Axios 自动带 CSRF Token axios.defaults.xsrfCookieName = 'XSRF-TOKEN'; axios.defaults.xsrfHeaderName = 'X-XSRF-TOKEN'; // 如果用 JWT Token 认证,可以关闭 CSRF(因为不用 Cookie) @Configuration public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) { http.csrf(csrf -> csrf.disable()); // JWT 时关闭 } }
面试金句 CSRF 攻击利用的是浏览器自动携带 Cookie 的机制——恶意网站构造 POST 请求到银行 API,浏览器自动带上用户的 Session Cookie。防御核心:JWT Token 放 Authorization Header(非 Cookie)天然免疫 CSRF。如果用 Cookie 认证,必须配 SameSite=Strict 或 CSRF Token。

8. CSP — 内容安全策略

CSP = 门禁白名单 只有名单上的人能进,名单外的全拦
什么时候启用 CSP
  • 生产环境必开:所有上线项目 — 防止 XSS 注入的最后一道防线
  • 有用户生成内容:评论、文章、备注 — 用户可能注入恶意脚本
  • 第三方SDK多:接入各种第三方 — 需要限制脚本来源

💻 CSP 配置

📀 nginx
📁 nginx/conf.d/
security.conf
proxy.conf
ssl.conf
// Nginx 配置 CSP Header add_header Content-Security-Policy " default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://api.example.com; font-src 'self' https://fonts.googleapis.com; frame-src 'none'; "; // Spring Boot 配置 @Bean public WebSecurityCustomizer cspCustomizer() { return web -> web.httpStrictTransportSecurity() .addHeaderWriter(new ContentSecurityPolicyHeaderWriter( "default-src 'self'; script-src 'self'" )); }
面试金句 CSP(Content Security Policy) 是 XSS 防御的最后一道防线:通过 HTTP 头声明资源加载白名单(script-src/style-src/img-src),浏览器拒绝加载不在白名单的资源。default-src 'self' 是最严格策略——只允许同源资源。部署策略:先用 Content-Security-Policy-Report-Only(仅报告不拦截)收集违规,再切换到强制模式。
⚠️ CSP 常见坑:Report-Only 模式先观察 → 确认没有误拦截 → 再切到强制模式。直接上强制 CSP 可能导致页面功能异常。

9. Git 规范 — 协作流程决策

📊 Git 分支策略决策表

策略分支模型适合复杂度
GitHub Flowmain + feature/*持续部署项目
Git Flowmain + develop + feature/* + release/* + hotfix/*版本发布项目
Trunk Basedmain + 短命 feature 分支高频发布 + CI/CD 成熟

💻 Commit 规范 + husky

📀 frontend-app
📁 /
commitlint.config.js
.husky/commit-msg
package.json
// Commit Message 格式 // <type>(<scope>): <subject> // // type: // feat: 新功能 // fix: 修复bug // docs: 文档 // style: 格式(不影响逻辑) // refactor: 重构 // perf: 性能优化 // test: 测试 // chore: 构建/工具 // // 示例: // feat(订单): 新增批量导出功能 // fix(登录): 修复Token过期后无限刷新 // perf(列表): 虚拟滚动优化大数据渲染 // 安装 commitlint + husky // npm install -D @commitlint/cli @commitlint/config-conventional husky // npx husky init // echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg // commitlint.config.js export default { extends: ['@commitlint/config-conventional'] };
面试金句 Conventional Commits 规范(feat/fix/docs/refactor/perf/test/chore)让 commit message 机器可读,配合 commitlint + husky 在 git commit 时自动校验格式。自动生成 CHANGELOG:standard-version / semantic-release 根据 commit type 自动语义化版本号和变更日志。scope 用于标识影响范围,方便 code review 和 blame 定位。

🔧 前端工程化与安全场景决策 · 全栈资料库

← 返回场景决策