MisakaJimmy Blog Logo
  • Docs
  • GitHub Repo

Lifelong Learning

Frontend

Web IDE 开发笔记

Theia 架构解析

Lumino:桌面感窗口系统的前世今生

Lumino 的 Widget 系统:从概念到源码入口

  • Widget 在 Lumino 里的角色
  • 一个最小可跑的 Lumino Widget Demo
  • Widget 的生命周期:attach/detach/resize/update
  • Widget 与容器:Panel / DockPanel / TabBar 的关系
  • Widget 与信号/命令:更大一层的协作
  • 写在最后:为什么先啃 Widget 再看 Theia?

Lumino 的 signaling 和 messaging:状态与生命周期的底噪

  • 先分清楚:signaling vs messaging 到底谁管啥?
  • signaling:在 Widget / 模型之间传递“我变了”的信号
  • signaling + Widget 的一个组合小例子
  • messaging:Widget 生命周期背后那条消息泵
  • signaling + messaging 在实际阅读代码时的用法区别
  • 小结:为什么我愿意为这俩单独写一篇?

Lumino 的布局系统:DockPanel / SplitPanel / TabBar 一条龙

  • 布局的基本思路:一堆容器 Widget 叠罗汉
  • SplitPanel:最基础的“可拖动分隔条”
  • TabBar / TabPanel:一组 Widget 共用一个“框”,靠 Tab 切换
  • DockPanel:把 Split + Tab 全打包了
  • 布局数据的持久化和恢复(IDE 必备套路)
  • 这些布局 Widget 在 Theia 里的大致落位
  • 小结:把这几块积木认清楚,再看 IDE 布局就不那么迷幻了

Lumino 的 command 系统:把行为从按钮里解放出来

  • 先理解一下:为什么需要 command 系统?
  • CommandRegistry:命令的集中注册中心
  • 命令与快捷键:addKeyBinding、键盘处理与 FocusTracker
  • 命令与菜单/按钮:不同入口复用同一段逻辑
  • 命令参数与上下文:不只是“开关”动作
  • 在 Theia / Lumino 源码里看 command 的一些观察点
  • 小结:command 系统 = 行为的“中枢神经”

Lumino 的应用骨架:Application + 菜单 / 工具栏 / 右键菜单

  • @lumino/application:把零散的能力装进一个 App
  • 一个极简 Lumino Application 骨架
  • 菜单栏:Menu + MenuBar
  • 右键菜单:ContextMenu
  • 工具栏:一组“命令按钮”的容器
  • 把这些拼回 Application 视角
  • 小结:Application + 菜单体系 = 把“命令世界”塞进一个真正的 App

Lumino 的 virtualdom:轻量 VDOM、对比 React/Vue 以及如何结合使用

  • @lumino/virtualdom 是什么?
  • 和 React/Vue 的对比:它刻意“不长大”的地方
  • 在 Widget 里使用 virtualdom:一个完整小例子
  • 如果工程里已经有 React/Vue,要怎么和 Lumino 配合?
    • 1. Lumino 作为“外壳”,React/Vue 作为内部视图
    • 2. React/Vue 作为主 UI,Lumino 组件嵌进去(不太常见但可以)
    • 3. virtualdom 自己 + React/Vue 混用?不推荐硬混
  • 和 React/Vue 相比,什么时候更适合用 Lumino 自己的 virtualdom?

Lumino 的 disposable 与组件生命周期:东西造出来,总要有人负责善后

  • @lumino/disposable:一个很小但到处都在用的模式
  • 把 disposable 和 Widget 生命周期结合起来
  • 常见组件的生命周期:从 Application 到 Widget
    • 1. Application 层
    • 2. Shell / 布局层
    • 3. 单个 Widget 层
  • 在 Theia/Lumino 里看“生命周期 + 资源释放”的几个观察点
  • 小结:disposable 是“看不见,但处处在”的一层保障

Lumino 的性能与优化:与 React 的对比思考

  • 先说定位:Lumino 关心的“性能问题”跟普通业务前端不太一样
  • Lumino 层面的性能基石:三块砖
  • 和 React 的几个典型对比点
    • 1. 更新触发的心智模型
    • 2. diff 粒度与重绘策略
    • 3. 布局和重排成本
  • 在 Lumino 里常见的几个性能坑 & 优化思路
    • 1. 不要滥用 update(),尤其是“级联 update”
    • 2. 大量 Widget 并存时,注意生命周期清理
    • 3. 布局树的复杂度控制
  • 当你在 Theia 上做二次开发时,可以关注的性能点
  • 小结:别指望它像 React 一样“自动聪明”,但它给了你足够的控制力

Lumino 在视频编辑器等工具类应用中的可能性与想象

  • 为什么一提视频编辑器,就容易想到 Lumino 这种框架?
  • 用 Lumino 搭一个视频编辑器大致会怎么分层?
  • 一些具体的 UI 例子:Lumino 能帮上哪些忙?
    • 1. 时间线与多轨布局
    • 2. 可停靠的工具面板
    • 3. 复杂表格/列表:素材管理、效果列表
  • 和 React/Vue 生态结合的想象
  • 实际上有没有类似方向的项目?
  • 小结:把 Lumino 当成“通用工具类应用壳”的一个选项

Lumino 的工具与基础设施模块:与 Lodash 的对比杂谈

  • 先定个调:这是“框架内部基建”,不是“业务工具库”
  • @lumino/algorithm:一小撮“拿来就用”的算法积木
  • @lumino/collections:为框架准备的容器,而不是通用 Map/Set 替代品
  • @lumino/properties:给对象挂“扩展属性”的正规方式
  • @lumino/polling:比 setInterval 高一档的轮询封装
  • 这些模块在整个 Lumino / Theia 里的角色
  • 小结:什么时候该想起它们,而不是顺手就 Lodash 一把梭?

Monaco:前世今生与在 Theia 中的角色

Monaco 与 Theia:MonacoInit 与编辑器装配流程

  • 从入口里的 MonacoInit.init(container) 说起
  • MonacoInit 负责的主要任务
  • Monaco 前端模块大致包含什么
  • 从 EditorManager 一路走到 Monaco 编辑器实例
  • 编辑器 Widget 如何落到 Lumino 布局里
  • 小结:MonacoInit 把编辑器这一块“挂”进了 Theia 的骨架

Monaco 核心概念:Model / Editor / View 与 Theia 抽象

  • 文本模型(ITextModel):真正存放代码内容的地方
  • 编辑器实例(IStandaloneCodeEditor):操作模型的入口
  • 一个 Model 可以挂多个 Editor
  • View 的角度:模型是数据,编辑器是视图 + 控制
  • 小结:先牢牢记住“一个模型,多种视图”的图景

Monaco 语言与高亮:注册语言、Monarch 语法与 Theia 映射

  • 注册一种语言的基本步骤
  • 用 Monarch 定义语法高亮规则
  • 主题如何把 token 映射为颜色
  • 在 Theia 中语言注册的典型链路
  • 与 LSP 和语言特性的结合
  • 小结

Monaco 装饰器与标记:deltaDecorations、Gutter 与 Theia Markers

  • 装饰器的基本概念
  • deltaDecorations:增量更新装饰器
  • 常见装饰器选项
  • Theia 的 Markers 如何映射到装饰器
  • 其它基于装饰器的功能
  • 小结

Monaco 命令与操作:Editor Actions、快捷键与 Theia 命令系统

  • Editor Action:在编辑器上挂操作
  • 快捷键与 Keybinding 配置
  • Theia 中的命令系统与 Monaco Action 的关系
  • 两套命令系统的协同思路
  • 小结

Monaco 的 diff 编辑器、多模型与大文件场景

  • diff 编辑器的基本用法
  • 多模型并存:资源管理与标识
  • 大文件场景:Monaco 的行为与限制
  • 多模型 + 大文件下的一些注意点
  • 小结

Monaco 性能与优化:渲染、事件与资源管理

  • 渲染与布局:避免不必要的重排
  • 事件风暴:谨慎处理变更与光标事件
  • 装饰器数量:成千上万的标记也要有节制
  • 多模型与资源管理:防止模型泄漏
  • 大文件:功能与性能之间的取舍
  • 小结

InversifyJS:Theia 架构的依赖注入基石

InversifyJS:依赖注入的前世今生(从工厂模式到 Theia)

  • 一切从“直接 new 依赖”开始
  • 手工构造 + 工厂模式:第一步解耦
  • Java 世界的答案:Spring / Guice / CDI 等 DI 容器
  • 回到 JavaScript/TypeScript:为什么也需要 DI?
  • InversifyJS:把 Java 世界那套“DI 思维”搬到 TS 上
  • 为什么 Theia 这么重度使用 InversifyJS?
  • 小结:先有“为什么需要 DI”,才有“选 InversifyJS”

在项目中引入 InversifyJS:配置与依赖

  • 安装依赖
  • TypeScript 配置:开启装饰器支持
  • 引入 reflect-metadata
  • 环境支持与 polyfills
    • 必需特性
    • 可选特性(仅在特定场景需要)
  • 在 Theia 项目中的情况
  • 常见问题排查

InversifyJS 基础示例:从传统依赖到依赖注入

  • 代码解析:一步步理解依赖注入
    • 第一步:定义服务标识符(Symbol)
    • 第二步:定义业务类
    • 第三步:标记类为可注入
    • 第四步:注册绑定关系
    • 第五步:从容器获取实例
  • 这个例子说明了什么?
  • 下一步:更复杂的场景

InversifyJS:服务标识符与接口绑定(Symbol 与接口)

  • 服务标识符到底是干嘛用的?
  • 为什么推荐用 Symbol 而不是字符串?
  • 接口绑定:在类型层面隐藏实现细节
  • 类作为标识符 vs Symbol 作为标识符
  • 在 Theia 源码里可以怎么“练习找一找”?

用类本身作为服务标识符:简化绑定的另一种方式

  • 类作为标识符的基本用法
  • 使用 toSelf() 简化绑定
  • 已知局限性:循环依赖的问题
  • 在 Theia 里的实践建议
  • 小结

InversifyJS:作用域与生命周期(Singleton / Transient 等)

  • 三种常见作用域
  • 在 Theia 里,哪些东西应该是单例?
  • 哪些场景更适合 transient(每次一个新实例)?
  • 生命周期与资源释放:和 disposable 的关系
  • 在 Theia 源码里如何“感受”这些作用域?

InversifyJS:多种绑定方式(to / toSelf / toConstantValue / toDynamicValue / toFactory / toProvider)

  • 1. to:最常见的“接口 → 实现类”绑定
  • 2. toSelf:具体类自己就是标识符
  • 3. toConstantValue:绑定常量/配置/单例对象
  • 4. toDynamicValue:按需、惰性、基于上下文生成实例
  • 5. toFactory:返回一个“工厂函数”
  • 6. toProvider:支持异步创建(返回 Promise 的工厂)
  • 小结:选哪种绑定,取决于“对象是谁创建的”和“何时创建”

InversifyJS:高级绑定(命名绑定、标签绑定、多重注入、可选注入)

  • 命名绑定:一个接口,多种实现,用名字区分
    • 注册阶段
    • 注入阶段
  • 标签绑定:用键值对来表达“这个实现的特性”
    • 注册阶段
    • 注入阶段
  • 多重注入:一次性拿到“这一类所有实现”
    • 注册阶段:正常多次 bind 即可
    • 注入阶段:用 @multiInject
  • 可选注入:这个依赖可能没有也没关系
  • 在 Theia 里的影子

InversifyJS:ContainerModule 与模块化 DI(对标 Theia 前后端模块)

  • 为什么需要 ContainerModule?单文件 bind() 太乱了
  • ContainerModule:把一组绑定封成一个模块
  • AsyncContainerModule:支持异步初始化的模块
  • 对标 Theia:*-frontend-module / *-backend-module 本质上就是 ContainerModule
  • 模块之间的依赖关系:松耦合的“功能拼图”
  • 在自己项目里怎么设计模块粒度?
  • 小结:ContainerModule 是把 DI 从“单文件配置”提升到“功能级别模块”的关键

InversifyJS:懒注入与循环依赖(lazyInject 的利与弊)

  • 先回顾一下:循环依赖在 DI 容器里为什么麻烦?
  • inversify-inject-decorators 与 lazyInject
  • 示例:用 lazyInject 缓解循环依赖
  • 懒注入不是银弹:它解决的是“访问时机”,不是“设计问题”
  • 在 Theia 这种架构里,应该怎么看待懒注入?
  • 小结:把 lazyInject 当成“特例工具”,而不是日常注入方式

InversifyJS:测试中的容器用法(测试容器与 rebind)

  • 两种基本策略:测试容器 vs 重绑定
  • 建一个最小测试容器
  • 在现有容器上用 rebind 替换实现
  • 针对 Theia 的一些具体建议
  • 一些实用的小技巧
  • 小结:把容器当成“测试夹具”的一部分

InversifyJS 与 Theia:从 index.js 看前端启动与模块装配

  • 这个 index.js 在 Theia 里扮演什么角色?
  • Container:Theia 前端世界的“装配厂”
  • container.load(module):Theia 模块 = 一堆 InversifyJS 绑定
  • preload:在应用真正启动前做准备工作
  • 最后一步:从容器拿出 FrontendApplication 并启动
  • 这份 index.js 给我带来的几个 InversifyJS 认知

InversifyJS 与 Theia:概念对照表(从 DI 到扩展点)

  • 总览:一张小表先看个大概
  • 容器与模块:应用壳 + 功能拼图
  • 服务标识符与接口:Symbol 作为“运行时接口名”
  • 绑定方式:从简单服务到工厂/Provider
  • 多实现与扩展点:multiInject 对应 Theia 的 Contribution 模式
  • 作用域与生命周期:单例服务 vs 瞬时 Widget
  • 懒注入、可选注入:特殊场景下的工具- InversifyJS:
  • 容器在测试里的角色:测试夹具
  • 最后一小节:一条“从 InversifyJS 到 Theia”的心智路径

LSP:语言服务器协议的前世今生与在 Theia 中的角色

LSP 协议核心与常见请求:从文档同步到补全诊断

  • 消息结构与传输方式概览
  • 初始化阶段:initialize / initialized
  • 文档同步:didOpen / didChange / didSave / didClose
  • 补全:textDocument/completion
  • 悬停与跳转:hover / definition / references
  • 诊断与问题列表:publishDiagnostics
  • 小结

LSP 在 Theia 中的客户端架构:前端、后端与语言服务管理

  • 角色分工概览
  • 前端:LSP 客户端与编辑器的衔接
  • 后端:语言服务器进程与连接管理
  • 前后端之间的桥接:消息通道与文档路由
  • 多语言与多 Language Server 管理
  • 与依赖注入和扩展点的结合
  • 小结

LSP 与 Monaco 的适配:诊断、补全与跳转在编辑器中的落地

  • 诊断:从 publishDiagnostics 到 Markers 再到装饰器
  • 补全:LSP completion 结果到 Monaco CompletionItem
  • 悬停信息:hover 到悬浮气泡
  • 跳转定义与引用:LSP definition/references 到编辑器导航
  • 命令体系中的一环:从 Theia 命令到 LSP 请求再到 Monaco 行为
  • 小结

LSP 最小示例:一个简单 Language Server 与 Theia 扩展示意

  • 一个极简 Language Server 的骨架
  • 在 Theia 中声明一个语言客户端贡献点
  • 服务器如何被 Theia 启动
  • 端到端效果会是什么样

LSP 多语言与多服务器管理:配置、路由与性能考虑

  • 多语言支持的基本配置思路
  • 语言到服务器的映射与路由
  • 多服务器并存下的资源与生命周期管理
  • 请求并发与响应性能
  • 与工作区和文件系统的协同
  • 小结

AST:语法树到底是什么,以及和日常开发有什么关系

AST:前端常见语法树工具链一览(TypeScript / Babel / ESLint / SWC)

  • 几个常见名字先对上号
  • TypeScript AST:TS 项目里的“首选工具”
  • Babel / ESTree:JS 世界的“通用语法树语言”
  • ESLint:站在 AST 上的一层“规则框架”
  • SWC / esbuild:更偏构建方向的 AST

AST:TypeScript 编译器 API——从源码到语法树与简单分析

  • 准备一个最小的 TS AST 实验环境
  • 遍历 AST:找到所有函数声明
  • 一个更实际一点的例子:找出所有 console.log
  • 再往前一步:借助 TypeChecker 做简单类型分析
  • 和 LSP / Theia 里的那套有什么关系?

AST:检测与自动修复——从规则到 CodeAction

  • 一个最简单的检测规则:找出所有 var
  • 生成修复后的代码
  • 一个更实际的例子:检测未使用的导入
  • 在 LSP CodeAction 里的落地
  • 和 ESLint / Prettier 的关系
  • 小结

AST 到编辑器 UI 的完整闭环:从语法树到 LSP 再到 Monaco

  • 在 Language Server 里做 AST 分析
  • 把 AST 分析结果转换成 LSP 协议格式
    • Diagnostics:从 AST 节点到 LSP Range
    • Completion:从 AST 上下文到补全项
    • Hover:从 AST 节点到类型信息
  • Theia 前端:接收 LSP 消息并适配到 Monaco
    • Diagnostics → Monaco 装饰器
    • Completion → Monaco CompletionItemProvider
    • Hover → Monaco HoverProvider
  • 一个完整的流程示例
  • 小结

AST:跨文件分析与项目级代码理解——从单文件到整个项目

  • 从单文件到项目级:为什么需要跨文件分析
  • TypeScript Program:把多个文件的 AST 组织起来
  • 符号表:从 AST 节点到跨文件的符号
  • 查找所有引用:在整个项目里追踪符号
  • 跨文件的导入/导出分析
  • 在 Language Server 里的实际应用
    • 维护项目状态
    • 实现跨文件的 LSP 功能
  • 性能考虑:增量更新与缓存
  • 小结

AST:调试与可视化——从查看结构到开发工具链

  • 最简单的调试:打印 AST 结构
  • 使用 TypeScript Compiler API 的内置工具
  • AST Explorer:在线可视化工具
  • TypeScript AST Viewer
  • 调试 AST 转换:打印前后对比
  • 在 Language Server 里调试 AST
    • 使用日志输出
    • 使用调试器断点
    • 输出中间结果到文件
  • 可视化 AST 的工具函数
  • 在 Theia 里调试 Language Server
  • 常见调试场景
    • 场景1:节点类型判断错误
    • 场景2:位置信息不对
    • 场景3:转换后代码格式丢失
  • 小结

前端常用工具链

前端打包工具对比:从 Webpack 到 Vite 的发展与选择

  • 打包工具的发展历程
    • 早期:Grunt 和 Gulp(任务运行器时代)
    • Webpack 时代(2014-至今)
    • Rollup(2015)
    • Parcel(2017)
    • Vite(2020)
    • esbuild(2020)和 SWC(2020)
    • Turbopack(2022)
  • 主流工具对比
    • Webpack
    • Vite
    • Rollup
    • Parcel
    • esbuild
  • 性能对比
    • 开发服务器启动时间
    • HMR 速度
    • 生产构建速度
    • 打包体积
  • 选用建议
    • 选择 Webpack 当:
    • 选择 Vite 当:
    • 选择 Rollup 当:
    • 选择 Parcel 当:
    • 混合使用
  • 迁移建议
    • 从 Webpack 迁移到 Vite
    • 从其他工具迁移
  • 未来趋势
    • 1. 更快的构建工具
    • 2. 零配置趋势
    • 3. 原生 ES 模块支持
    • 4. 增量编译
  • 小结

Yarn

  • 安装yarn
    • 下载 nodejs 通过 npm 安装
    • 查看版本
    • 设置淘宝源
  • yarn 与 npm 命令对比
  • npm --save 和 npm --save-dev 区别
  • yarn对比npm的优点

Lerna

  • 关于
    • Lerna repo 是什么样的?
    • Lerna 能做什么?
    • Lerna 不能做什么?
  • 入门
  • 如何使用Lerna
    • Fixed/Locked 模式 (default)
    • Independent 模式
  • 基本概念
    • lerna.json
      • 废弃字段
    • 常见的devDependencies
    • Git 托管的依赖项
  • 自述文件徽章

Node-gyp 与 Node Headers 原理解析

  • 一句话解释
  • 1. 为什么需要 node-gyp?
  • 2. node-gyp 实际做了什么?
  • 3. 什么是 Node Headers?
  • 4. 为什么国内经常卡在下载阶段?
  • 5. 在 IDE / 工具链场景中的典型应用
  • 6. 未来在 AI IDE 中的潜在价值
  • 总结

前端基础

ECMAScript 版本变迁:从 ES5 到 ES2024 的语法演进

  • ES5(2009):现代 JavaScript 的起点
    • 核心特性
  • ES6 / ES2015:JavaScript 的“现代化”
    • 核心特性
  • ES2016:小幅更新
  • ES2017:async/await 的引入
  • ES2018:异步迭代和对象展开
  • ES2019:数组和字符串的增强
  • ES2020:BigInt 和可选链
  • ES2021:逻辑赋值和数字分隔符
  • ES2022:类字段和顶层 await
  • ES2023:数组查找方法
  • ES2024:数组分组和 Promise.withResolvers
  • 版本变迁对前端开发的影响
    • 语法层面的演进
    • 工具链的适配
    • 浏览器兼容性
    • 在 AST 层面的体现
  • 小结

JavaScript 异步编程:从回调到 Promise 再到各种骚操作

  • 为什么需要异步?
  • 回调函数:最原始的异步方式
  • Promise:异步编程的基础
    • Promise 基础
    • Promise 的三种状态
    • Promise 链式调用
    • Promise 的常用方法
      • Promise.all:等待所有 Promise 完成
      • Promise.allSettled:等待所有 Promise 完成(无论成功或失败)
      • Promise.race:返回第一个完成的 Promise
      • Promise.any:返回第一个成功的 Promise
  • async/await:让异步代码看起来像同步代码
    • 基础用法
    • 错误处理
    • 并行执行
  • 常用操作和模式
    • 1. 重试机制
    • 2. 并发控制:限制同时执行的异步操作数量
    • 3. 防抖和节流
    • 4. 超时包装器
    • 5. 取消 Promise
    • 6. 批量处理:分批执行异步操作
    • 7. 顺序执行:一个接一个处理
    • 8. 条件执行:根据条件决定是否执行异步操作
    • 9. 缓存 Promise:避免重复请求
    • 10. Promise 队列:按顺序执行异步任务
    • 11. 异步迭代器:处理流式数据
    • 12. 错误重试的指数退避
  • 实际开发中的最佳实践
    • 1. 总是处理错误
    • 2. 避免在循环中使用 await
    • 3. 使用 Promise.allSettled 处理部分失败
    • 4. 合理使用 async/await 和 Promise 方法
  • 小结

JavaScript 中的隐秘问题:那些容易踩的坑

  • 类型转换的陷阱
    • == vs ===
    • 数组和数字的转换
    • 布尔值的转换
    • parseInt 的陷阱
  • 作用域和变量提升
    • var 的作用域问题
    • 变量提升(Hoisting)
    • 函数提升
  • this 绑定的陷阱
    • 普通函数中的 this
    • 回调函数中的 this
    • 箭头函数的 this
  • 数组的奇怪行为
    • 稀疏数组
    • 数组的 length 属性
    • 数组方法返回新数组还是修改原数组
    • 数组的 sort 方法
  • 对象的陷阱
    • 对象属性的访问
    • 对象属性的枚举
    • 对象比较
  • 浮点数精度问题
  • 原型链的陷阱
    • 原型污染
    • 原型链查找的性能
    • hasOwnProperty 的问题
  • 异步相关的陷阱
    • 循环中的异步
    • Promise 的错误处理
    • async/await 的错误处理
  • 其他常见的坑
    • typeof 的陷阱
    • NaN 的问题
    • 字符串和数字的运算
    • 函数参数的默认值
    • 解构赋值的陷阱
    • JSON.stringify 的陷阱
    • 正则表达式的全局标志
  • 如何避免这些问题
    • 1. 使用严格模式
    • 2. 使用现代语法
    • 3. 使用工具
    • 4. 理解 JavaScript 的特性
  • 小结

前端中的常用算法:从数据结构到性能优化

  • 数组操作算法
    • 数组去重
    • 数组扁平化
    • 数组分组
    • 数组分块
    • 数组交集、并集、差集
  • 排序算法
    • 快速排序
    • 归并排序
    • 堆排序
  • 查找算法
    • 二分查找
    • 深度优先搜索(DFS)
    • 广度优先搜索(BFS)
  • 字符串算法
    • 字符串匹配:KMP 算法
    • 最长公共子序列(LCS)
    • 编辑距离(Levenshtein Distance)
  • 树和图的算法
    • 二叉树遍历
    • DOM 树遍历
    • 虚拟 DOM Diff 算法(简化版)
  • 缓存算法
    • LRU 缓存(Least Recently Used)
    • LFU 缓存(Least Frequently Used)
  • 性能优化算法
    • 防抖(Debounce)
    • 节流(Throttle)
    • 函数记忆化(Memoization)
  • 其他实用算法
    • 洗牌算法(Fisher-Yates)
    • 加权随机选择
    • 滑动窗口
  • 小结

TypeScript

TypeScript 高级类型:联合、交叉、字面量类型与类型守卫

  • 联合类型(Union Types)
    • 基础用法
    • 联合类型的类型收窄
    • 联合类型与数组
    • 联合类型与对象
  • 交叉类型(Intersection Types)
    • 基础用法
    • 交叉类型与对象合并
    • 交叉类型与函数
    • 交叉类型的实际应用
  • 字面量类型(Literal Types)
    • 字符串字面量类型
    • 数字字面量类型
    • 布尔字面量类型
    • const 断言
  • 类型守卫(Type Guards)
    • typeof 类型守卫
    • instanceof 类型守卫
    • in 操作符类型守卫
    • 自定义类型守卫函数
    • 可辨识联合(Discriminated Unions)
  • 类型别名 vs 接口
    • 类型别名(Type Aliases)
    • 接口(Interfaces)
    • 区别和选择
  • 索引签名和映射类型基础
    • 索引签名
    • 只读索引签名
    • 映射类型基础
  • 实际应用场景
    • API 响应类型
    • 配置对象类型
  • 小结

TypeScript 泛型:从基础到进阶

  • 泛型基础
    • 为什么需要泛型?
    • 泛型函数
    • 泛型接口
    • 泛型类
  • 泛型约束
    • extends 约束
    • keyof 约束
    • 多个约束
  • 泛型工具类型
    • Partial
    • Required
    • Readonly
    • Pick<T, K>
    • Omit<T, K>
    • Record<K, T>
    • Exclude<T, U>
    • Extract<T, U>
    • NonNullable
    • Parameters
    • ReturnType
    • ConstructorParameters
    • InstanceType
  • 条件类型(Conditional Types)
    • 基础语法
    • 条件类型的实际应用
    • infer 关键字
  • 分布式条件类型
    • 实际应用:过滤类型
    • 实际应用:提取函数重载的返回类型
  • 实际应用场景
    • API 响应类型
    • 深度只读类型
    • 深度可选类型
    • 函数重载类型
    • 类型安全的 EventEmitter
  • 小结

TypeScript 类型操作:类型推断、断言、收窄与兼容性

  • 类型推断(Type Inference)
    • 基础类型推断
    • 最佳公共类型推断
    • 上下文类型推断
    • 函数返回类型推断
    • 类型推断的限制
  • 类型断言(Type Assertions)
    • as 语法
    • 语法
    • 双重断言
    • 非空断言
    • 类型断言的注意事项
  • 类型收窄(Type Narrowing)
    • typeof 收窄
    • instanceof 收窄
    • in 操作符收窄
    • 相等性收窄
    • 真值收窄
    • 自定义类型守卫收窄
    • 可辨识联合收窄
    • 赋值收窄
    • 控制流分析
  • 类型兼容性
    • 对象类型兼容性
    • 函数类型兼容性
    • 可选参数和剩余参数
    • 枚举类型兼容性
    • 类类型兼容性
    • 泛型类型兼容性
    • 协变和逆变
  • 实际应用场景
    • 类型安全的 API 调用
    • 类型收窄在错误处理中的应用
    • 类型兼容性在函数重载中的应用
  • 小结

TypeScript 类与接口:面向对象编程

  • 类的基础
    • 类的定义
    • 类的访问修饰符
    • readonly 修饰符
    • 参数属性
    • 静态成员
    • 静态块
  • 类的继承
    • 基础继承
    • 方法重写
    • 访问修饰符在继承中的行为
  • 抽象类
    • 抽象类定义
    • 抽象属性
  • 接口(Interfaces)
    • 接口定义
    • 只读属性
    • 函数类型接口
    • 索引签名
    • 接口继承
    • 接口合并(Declaration Merging)
  • 类实现接口
    • 实现单个接口
    • 实现多个接口
    • 接口继承类
  • 类与接口的区别
    • 类型层面
    • 实现层面
    • 继承和扩展
    • 选择建议
  • 实际应用场景
    • 依赖注入模式
    • 策略模式
    • 工厂模式
    • 单例模式
  • 小结

TypeScript 工具类型:内置工具类型详解

  • 基础工具类型
    • Partial
    • Required
    • Readonly
    • Pick<T, K>
    • Omit<T, K>
    • Record<K, T>
  • 条件类型工具
    • Exclude<T, U>
    • Extract<T, U>
    • NonNullable
  • 函数类型工具
    • Parameters
    • ReturnType
    • ConstructorParameters
    • InstanceType
  • 字符串操作工具类型
    • Uppercase<S>
    • Lowercase<S>
    • Capitalize<S>
    • Uncapitalize<S>
  • 自定义工具类型
    • 深度 Partial
    • 深度 Required
    • 深度 Readonly
    • 可选属性转必需
    • 函数参数提取
    • 数组元素类型提取
    • Promise 类型提取
    • 对象值类型提取
    • 键值对反转
  • 实际应用场景
    • API 响应类型转换
    • 表单字段类型
    • 配置对象类型
  • 小结

TypeScript 模块与命名空间

  • ES 模块
    • 导出(Export)
    • 导入(Import)
    • 动态导入
  • 命名空间(Namespaces)
    • 命名空间定义
    • 多文件命名空间
    • 命名空间别名
  • 声明合并(Declaration Merging)
    • 接口合并
    • 命名空间合并
    • 命名空间与类合并
    • 命名空间与函数合并
    • 命名空间与枚举合并
  • 模块解析
    • 模块解析策略
    • Node 模块解析
    • 路径映射
    • 类型声明文件查找
  • 三斜线指令
    • ///
    • ///
    • ///
  • 模块 vs 命名空间
    • 使用模块当:
    • 使用命名空间当:
  • 实际应用场景
    • 类型声明文件
    • 模块扩展
    • 环境声明
  • 小结

TypeScript 装饰器与元数据

  • 装饰器基础
    • 启用装饰器
    • 装饰器工厂
  • 类装饰器
    • 基础用法
    • 类装饰器工厂
    • 实际应用:依赖注入
  • 方法装饰器
    • 基础用法
    • 实际应用:日志装饰器
    • 实际应用:性能监控
  • 属性装饰器
    • 基础用法
    • 实际应用:验证装饰器
  • 参数装饰器
    • 基础用法
    • 实际应用:依赖注入
  • 访问器装饰器
    • 基础用法
  • 元数据反射 API
    • 安装
    • 基础用法
    • 实际应用:路由装饰器
  • 装饰器执行顺序
  • 实际应用场景
    • Angular 风格的依赖注入
    • 验证装饰器
  • 小结

TypeScript 配置与工程化

  • tsconfig.json 基础
    • 配置文件结构
    • 配置继承
  • 编译选项详解
    • 基础选项
    • 类型检查选项
    • 模块解析选项
    • 输出选项
    • 其他选项
  • 与构建工具集成
    • Webpack
    • Vite
    • Rollup
  • 类型声明文件
    • 声明文件类型
    • 为第三方库创建类型声明
    • 扩展全局类型
    • 模块扩展
  • 项目结构
    • 单项目结构
    • 多项目结构(Project References)
  • 实际应用场景
    • 开发环境配置
    • 生产环境配置
    • 测试环境配置
  • 最佳实践
    • 1. 使用严格模式
    • 2. 配置路径别名
    • 3. 启用增量编译
    • 4. 分离配置
  • 小结

TypeScript 实战:常见模式与最佳实践

  • 常见设计模式
    • 单例模式
    • 工厂模式
    • 策略模式
    • 观察者模式
  • 类型安全的 API 调用
    • API 响应类型
    • 类型安全的 HTTP 客户端
  • 错误处理模式
    • Result 类型
    • Option 类型
  • 常见错误和解决方案
    • 错误 1:类型断言过度使用
    • 错误 2:使用 any
    • 错误 3:忽略 null/undefined
    • 错误 4:函数参数类型不明确
    • 错误 5:忽略返回类型
  • 最佳实践
    • 1. 使用严格模式
    • 2. 优先使用接口而不是类型别名(当可能时)
    • 3. 使用类型守卫而不是类型断言
    • 4. 使用 const 断言获得更精确的类型
    • 5. 使用工具类型减少重复
    • 6. 合理使用泛型
    • 7. 使用可辨识联合
    • 8. 避免类型断言链
  • 性能优化
    • 1. 使用类型导入
    • 2. 启用增量编译
    • 3. 使用项目引用
  • 小结

Symbol

  • 语法
    • 参数
  • 描述
    • 全局共享的 Symbol
    • 在对象中查找 Symbol 属性
  • 属性

React Hooks 深入与实现思路:useState、useEffect 与自定义 Hooks

  • useState:渲染快照与更新批处理
    • 状态是渲染时刻的快照
    • 批量更新与「同步代码里读不到最新值」
  • useEffect:依赖数组和闭包陷阱
    • 依赖数组是「你用到了谁」,不是「你希望谁变化时触发」
    • 闭包造成的「过期值」问题
  • useMemo / useCallback:只优化「贵的那部分」
    • 缓存计算结果:useMemo
    • 缓存回调引用:useCallback
  • 自定义 Hooks:把「一小撮逻辑」拎出来
    • 适合抽成 Hook 的信号
    • 粒度控制:不要把一个组件整体包成一个 Hook
  • 小结

React 渲染机制与调度:Fiber、优先级与并发特性

  • 从「一口气渲染到底」到「可中断的渲染」
  • 两个阶段:render 与 commit
  • 优先级与任务调度
  • 并发特性:useTransition 与 useDeferredValue
    • useTransition:延后那部分「重的渲染」
    • useDeferredValue:延后那份「值的变化」
  • 重渲染与调度:几个容易混淆的点
    • 「渲染频率高」不一定等于「卡顿」
    • 「打断」不等于「丢掉」
  • 和日常开发的连接点

React 组件设计模式:容器/展示组件、自定义 Hooks 与控制反转

  • 容器组件 vs 展示组件
  • 从容器组件到自定义 Hooks
  • 受控组件与非受控组件
    • 受控组件:外界完全掌控
    • 非受控组件:自己内部管一部分
    • 受控/非受控的混合模式
  • 控制反转:让父层决定策略
    • 用回调开放关键环节
    • 用自定义 Hook 做「业务逻辑的控制反转」
  • 组合优先于继承
  • 小结

React 状态管理策略:从本地 State 到全局 Store

  • 状态的几种「归属」
  • 本地 State:能局部就不要全局
  • Context:负责「一片区域」的共享
    • Context 的性能问题
  • 服务器状态:用「远程状态库」管理
  • URL 状态:路由是「可分享的状态」
  • 什么时候需要全局 Store?
  • 画一张「状态拓扑图」
  • 小结

React 性能优化实战:重渲染分析与列表优化

  • 先看清楚谁在重渲染
  • 减少不必要的重渲染
    • 用 React.memo 缓住稳定的子组件
    • 拆分状态,避免「一变全变」
  • 列表优化:key、虚拟化和按需渲染
    • 正确使用 key
    • 虚拟列表:只渲染可见部分
    • 分块渲染与懒加载
  • 避免在渲染函数里做重活
  • 和并发特性的配合
  • 小结

React 表单与复杂交互:受控组件、校验与异步提交

  • 受控组件打底
  • 组织表单状态:值、错误、touched、dirty
  • 校验:时机与粒度
    • 同步校验
    • 异步校验
  • 异步提交与状态反馈
  • 表单库什么时候登场
  • 小结

React 与异步数据:SWR 模型、Suspense 思路与错误边界

  • SWR 模型:请求不只是“发一次”
  • 用 React Query 管服务器状态
  • 写入与乐观更新
  • Suspense 思路:把加载当作“渲染的一部分”
  • 错误边界:和异步数据配套出现的那一层
  • 和状态管理的分工
  • 小结

React 路由与应用结构:嵌套路由、布局组件与权限控制

  • 路由与布局:Outlet 和布局组件
  • URL 即状态:让可以分享的状态进路由
  • 权限控制:路由守卫与 UI 级别的限制
    • 路由层的保护(Protected Route)
    • UI 层的权限
  • 路由与状态管理的边界
  • 小结

React SSR 与 Hydration:Next.js 中的实践与坑点

  • SSR / SSG / ISR 是什么区别
  • Hydration:不是再渲染一遍
  • Next.js 中的页面渲染模式
  • 客户端组件与服务端组件(App Router)
  • 常见坑点与经验
    • 1. 只在浏览器存在的对象
    • 2. 随机数与时间戳
    • 3. 与全局状态/Context 的配合
    • 4. SEO 与性能之间的取舍
  • 小结

React 与 TypeScript:组件类型建模、Props、Ref 与多态组件

  • 函数组件的基本类型写法
  • 组合 HTML 属性:在自定义组件上透传原生 props
  • Ref 转发:forwardRef 的类型写法
  • 受控/非受控组件的联合 props
  • 多态组件:as 属性与元素类型推导
  • 组件组合时的 Props 传递
  • 小结

React 错误处理与稳定性:Error Boundary、日志与降级策略

  • Error Boundary:拦住渲染阶段的异常
  • 错误边界能捕获什么,不能捕获什么
  • 日志与监控:把错误送到正确的地方
  • 降级策略:局部挂了不代表整站崩盘
  • 与异步请求结合
  • 小结

React 组件库与设计系统:从基础组件到业务组件层

  • 分层:Basic / Composite / Business
  • 基础组件:贴近设计 Token
  • 组合组件:固化交互模式
  • 业务组件:贴业务,不贴基础设施
  • 主题与暗色模式
  • 可访问性(a11y)在组件库里的落地
  • 与第三方 UI 库的关系
  • 小结

DataBase

PostgreSQL

PostgreSQL Docker 启动

  • docker-compose

Windows PostgreSQL 使用

  • 添加 bin 到环境变量之中
  • 角色 "postgres" 不存在

AI

OpenClaw

  • 1. OpenClaw 为什么突然火起来
  • 2.1 Agent Runtime(持续运行的 AI)
  • 2.2 工具调用系统(Tool / Skills)
  • 2.3 Memory 系统
  • 2.4 多模型路由
    • CLI
    • Gateway
    • Agent Runtime
    • Tool Manager
    • LLM Router
  • RBAC 模型
  • OpenClaw 模型
  • Edict 的价值
    • 1. Multi-Agent 组织结构探索
    • 2. 引入治理层
    • 3. 可观测性
  • Edict 的局限
  • 6.1 Scaling(模型规模)
  • 6.2 推理计算(test-time compute)
  • 6.3 系统增强
  • 1. 训练成本爆炸
  • 2. benchmark 接近饱和
  • 3. 推理能力瓶颈
    • 1. 继续 Scaling
    • 2. 推理计算
    • 3. 新架构
    • 4. AI 系统化

© 2026