25 分钟
项目全解析

设计决策与工程实践

就盯着项目里的关键设计决策、性能优化、工程规范这三块。

  • 理解关键设计决策的权衡
  • 掌握性能优化策略
  • 了解 CSS 变量主题系统
  • 理解 PWA 和离线策略

关键设计决策

1. 为什么用 Monaco Editor 而不是轻量编辑器?

Monaco Editor(VS Code 同款)体积约 2MB,有语法高亮、自动补全、错误提示、多光标这些功能。编程教学里,编辑器体验直接影响学习感受。CodeMirror更轻量,但功能少。选Monaco,用动态import按需加载,不卡首屏。

2. 为什么课程内容用 TS 对象而不是 MDX?

MDX适合写文章,但课程得要高度结构化的交互组件,比如选择题、填空题、代码运行、判题这些。TS对象能做类型检查、自动补全,组件组合也灵活。CourseRenderer是根据type字段渲染对应组件的。

3. 为什么 Worker 用 Module 模式?

Python
# Worker 模式选择
print("""
经典 Worker: new Worker("worker.js")
  - 用 importScripts() 加载脚本
  - Pyodide v314+ 不支持!

Module Worker: new Worker("worker.js", { type: "module" })
  - 用 import/export 语法
  - 支持动态 import()
  - Pyodide v314+ 要求 Module Worker
  - 严格模式,作用域隔离更好
""")

性能优化策略

性能优化清单

代码分割Monaco Editor 动态 import(不阻塞首屏)Pyodide 按需加载(点击运行时才加载)每个课程页独立 chunk缓存策略Service Worker 缓存静态资源Pyodide WASM 文件长期缓存(带 hash)React Query 缓存课程数据渲染优化React Server Components(减少客户端 JS)静态生成 SSG(课程页预渲染为 HTML)CSS 变量主题切换(无重排)执行优化Web Worker 不阻塞主线程执行环境复用(不每次重启 Pyodide)命名空间清理(隔离但不重载)

CSS 变量主题系统

示例
/* globals.css 中的主题变量 */
:root {
  --primary: #4f46e5;
  --bg: #ffffff;
  --card: #f8fafc;
  --foreground: #0f172a;
  --border: #e2e8f0;
}

.dark {
  --primary: #818cf8;
  --bg: #0f172a;
  --card: #1e293b;
  --foreground: #e2e8f0;
  --border: #334155;
}

/* 所有组件用变量,不写死颜色 */
.button {
  background: var(--primary);
  color: var(--bg);
  border: 1px solid var(--border);
}
🐍CSS 变量 vs Tailwind dark: 前缀

Tailwind 的 dark: 前缀需要在每个类名前加 dark:,容易遗漏。换 CSS 变量方案:定义两套变量值,组件只引用变量名,切换 .dark class 就行。好处是:一处定义全局生效支持多主题不止深色/浅色运行时切换无闪烁代码更简洁。

PWA 离线策略

PWA 离线架构

Service Worker 缓存策略:预缓存(Install 时)应用外壳(HTML/CSS/JS)首次访问后立即可离线运行时缓存(访问时)Pyodide WASM 文件 → CacheFirst(长期缓存)课程内容 → StaleWhileRevalidate(先显示缓存,后台更新)CDN 包 → CacheFirst离线体验已加载的课程可离线学习代码运行完全离线(Pyodide 在本地)进度保存在 localStorage

安全设计

Python
# 安全措施
print("""
1. 代码执行安全
   - Pyodide 运行在浏览器沙箱
   - 无法访问用户文件系统
   - 无法访问 Cookie/localStorage(Worker 隔离)
   - 超时保护防止死循环

2. CSP 内容安全策略
   - script-src 'self'(只加载本站脚本)
   - 禁止内联脚本(除 Next.js 注入的)
   - frame-src 限制为 doubao.com

3. 依赖安全
   - 定期 npm audit
   - 不使用可疑包
""")
🐍工程化的本质

工程化不是堆砌工具,是:一致性(ESLint/Prettier 统一风格)自动化(测试/构建/部署流水线)可观测性(错误监控/性能指标)可维护性(类型安全/组件拆分/文档)。这个项目是纯前端,但每个环节都遵循工业级标准。

选择题

Pyodide WASM 文件应该用什么缓存策略?

选择题

相比给每个类名都写 dark: 前缀,CSS 变量主题方案的主要优势是?

资深工程师加餐

底层原理 · 大厂视角 · 工程经验,点卡片展开

移动网络不稳定,离线优先的思路是:本地是唯一可信数据源,UI 先读本地立即响应,后台再静默与服务器同步,冲突按策略合并。它带来秒开、可离线使用的体验,代价是要处理同步状态、冲突解决和幂等。本项目把课程与 Python 运行时全部内置、开箱即用,正是这一思想的体现——把「没有网络也能完整学习」当成核心能力而非降级方案。

挑战任务

用字典合并模拟 CSS 变量级联

简单+50 XP

深色主题不用重写全部变量,就在基础变量上覆盖同名项就行。写 apply_theme(base, dark),返回合并后的字典,dark 里的同名键覆盖 base 里的。

用字典合并模拟 CSS 变量级联
1 个测试用例

课后作业

性能审计

中等+25 XP

用 Chrome DevTools Lighthouse 对项目做审计,记录性能、可访问性、最佳实践、SEO 分数,提优化建议。

性能审计
1 个测试用例