朋友好学架构总览
从全局视角理解这个项目的技术架构和设计哲学
- 理解项目的整体架构选择
- 掌握纯前端架构的优势和局限
- 理解技术栈选型逻辑
- 了解项目的数据流
为什么是纯前端架构?
Codecademy、freeCodeCamp这类在线编程教学平台,得靠后端服务器跑用户的代码。朋友好学的设计不一样:完全在浏览器里跑Python,不用后端。
传统方案:用户代码 → 后端服务器执行 → 返回结果。问题:需要服务器成本并发限制安全风险(用户代码可能攻击服务器)网络延迟。Pyodide 方案:Python 编译为 WebAssembly,在浏览器沙箱中运行。优势:零服务器成本无限并发绝对安全(沙箱隔离)零延迟。代价:首次加载约 10MB(WASM 运行时),但可被 Service Worker 缓存。
技术栈全景
# 朋友好学技术栈
print("""
┌─────────────────────────────────────────────┐
│ 浏览器 │
│ ┌───────────────────────────────────────┐ │
│ │ Next.js 16 (App Router) │ │
│ │ ┌─────────┐ ┌──────────────────┐ │ │
│ │ │ React │ │ Monaco Editor │ │ │
│ │ │ UI 层 │ │ (代码编辑器) │ │ │
│ │ └────┬─────┘ └────────┬─────────┘ │ │
│ │ │ Zustand │ │ │
│ │ │ (状态管理) │ │ │
│ │ ┌────▼──────────────────▼──────────┐ │ │
│ │ │ Pyodide (WASM) │ │ │
│ │ │ CPython 3.14 编译为 WebAssembly│ │ │
│ │ │ 在 Web Worker 线程中运行 │ │ │
│ │ └──────────────────────────────────┘ │ │
│ └───────────────────────────────────────┘ │
│ Tailwind CSS │ Framer Motion │ localStorage│
└─────────────────────────────────────────────┘
│ │
Service Worker CDN (Pyodide包)
(离线缓存) (numpy/pandas)
""")关键技术选型理由
· 框架:Next.js 16 —— SSR / SSG + 路由 + 构建一体化· UI 库:自研 + Tailwind —— 极致定制,无组件库冗余· 编辑器:Monaco Editor —— VS Code 同款,功能最强· Python 运行时:Pyodide(WASM)—— 零后端、安全、零延迟· 状态管理:Zustand —— 轻量(1KB),API 简洁· 服务端状态:React Query —— 缓存、重试、后台刷新· 动画:Framer Motion —— 声明式 API,性能好· 样式:Tailwind CSS —— 原子化,零运行时开销· 数据持久化:localStorage —— 无需后端,离线可用· PWA:Service Worker —— 可安装、离线访问
数据流
理解数据流是理解整个项目的关键。
# 用户点击"运行"后的完整数据流
print("""
1. 用户在 Monaco Editor 中写代码
↓ onChange
2. React State 更新(code 变量)
↓ 点击"运行"
3. usePythonExecutor.run(code)
↓ postMessage
4. Web Worker 接收消息
↓ import Pyodide
5. Pyodide 在 WASM 中执行 Python
↓ stdout/stderr 回调
6. Worker 收集输出
↓ postMessage
7. 主线程接收结果
↓ setResult
8. React 重新渲染输出面板
↓
9. 判题引擎比对输出(如果是挑战题)
↓
10. Zustand 更新进度/XP/成就
↓
11. localStorage 持久化
""")Python 执行放在 Web Worker 中,不阻塞主线程。如果在主线程运行 Pyodide,执行死循环时整个页面会卡死。Worker 线程可以被 terminate() 强制终止,这是超时保护的基础。
朋友好学选择 Pyodide 而非后端执行 Python 的核心理由是什么?
朋友好学里,你写的 Python 代码实际运行在哪里?
资深工程师加餐
底层原理 · 大厂视角 · 工程经验,点卡片展开
UI、状态、业务逻辑、数据访问各层单向依赖:换一套 UI 不动业务,换一个数据源不动界面。依赖方向应向内收敛,最核心的业务规则尽量写成不依赖框架的纯函数——纯函数最好测、最好复用,这也是「整洁架构」思想在前端/客户端项目里的落地。
挑战任务
请求-响应配对(执行器核心思想)
主线程可能同时发多个请求,Worker 乱序返回结果。实现 match_order(request_ids, results):results 是若干 [请求id, 结果],返回按 request_ids 顺序排好的结果列表。
课后作业
画出架构图
拿纸笔或者画图工具,画出朋友好学的完整架构图,把每一层的技术和数据流向都标清楚。