加入 Lyt.js:从第一行代码到核心贡献者
137,439 行 TypeScript,32 个子包,2833+ 个测试用例,零运行时依赖。 这不是一个玩具项目 —— 这是一个完整的、可运行的前端框架。而今天,我要带你从零开始,一步步成为它的贡献者。
前言
你可能听说过 Vue、React、Svelte,但你听说过 Lyt.js 吗?
Lyt.js 是一个纯原生 TypeScript 实现的轻量级前端框架,当前版本 v5.0.1,采用 MIT 许可证。它拥有 32 个子包、91,227 行 TypeScript 源码(不含测试)、46,212 行测试代码,覆盖了从前端渲染到全栈框架的完整能力链路。
更重要的是 —— 它对新手贡献者非常友好。本文将手把手带你走完从克隆仓库到提交第一个 PR 的全流程。
一、认识 Lyt.js:项目全景
在动手之前,先花三分钟了解你要贡献的项目。
核心数据一览
| 指标 | 数据 |
|---|---|
| 当前版本 | v5.0.1 |
| 子包数量 | 32 个 |
| TypeScript 源码(不含测试) | 91,227 行 |
| 测试代码 | 46,212 行 |
| 全部 .ts 代码 | 137,439 行 |
| 测试用例 | 2,833+ 个 |
| 测试文件 | 78 个 |
| 运行时依赖 | 0 个 |
| Node 要求 | >= 18.0.0 |
| 包管理器 | pnpm (workspace) |
| 语言 | TypeScript (strict mode) |
| 许可证 | MIT |
三层架构设计
Lyt.js 采用清晰的分层架构,包间依赖关系如下:
┌─────────────────────────────────────────────────────┐
│ 应用层 (Application Layer) │
│ core / router / store / components / cli / ai │
│ compat / lytx / devtools │
└───────────────────────┬─────────────────────────────┘
↓
┌───────────────────────┴─────────────────────────────┐
│ 核心引擎层 (Core Engine Layer) │
│ reactivity / compiler / vdom / component / common │
└───────────────────────┬─────────────────────────────┘
↓
┌───────────────────────┴─────────────────────────────┐
│ 平台适配层 (Platform Adapter Layer) │
│ renderer (DOM / SSR / Vapor) │
└─────────────────────────────────────────────────────┘
reactivity 是整个框架的地基,被所有上层模块依赖。理解了这一点,你就抓住了阅读源码的钥匙。
32 个子包一览
| 包名 | 职责 | 层级 |
|---|---|---|
core | 核心入口,createApp、h()、插件系统 | 应用层 |
reactivity | 响应式系统,Proxy + Signal 双模式 | 核心引擎层 |
compiler | 模板编译器,SFC 编译,WASM 编译器 | 核心引擎层 |
renderer | 渲染器(DOM / SSR / Vapor) | 平台适配层 |
component | 组件系统,生命周期、Props、Slots | 核心引擎层 |
vdom | 虚拟 DOM,Block Tree + Patch Flag | 核心引擎层 |
common | 公共工具,事件总线、调度器 | 核心引擎层 |
router | 路由,History/Hash 双模式 | 应用层 |
store | 状态管理,Pinia 风格 API | 应用层 |
components | UI 组件库(50+ 组件) | 应用层 |
cli | 命令行工具,脚手架、开发、构建 | 应用层 |
ai | AI 辅助开发,代码补全、组件生成 | 应用层 |
compat | Vue 3 兼容层 | 应用层 |
lytx | 元框架,SSR/SSG/SPA 全栈渲染 | 应用层 |
devtools | 浏览器开发者工具 | 应用层 |
micro-frontend | 微前端 | 应用层 |
performance | 性能监控 | 应用层 |
plugin-sdk | 插件开发 SDK | 应用层 |
plugin-registry | 插件注册中心 | 应用层 |
plugin-auth | 认证插件 | 应用层 |
plugin-chart | 图表插件 | 应用层 |
plugin-highlight | 代码高亮插件 | 应用层 |
plugin-i18n | 国际化插件 | 应用层 |
plugin-logger | 日志插件 | 应用层 |
plugin-storage | 存储插件 | 应用层 |
plugin-theme | 主题插件 | 应用层 |
plugin-virtual-list | 虚拟列表插件 | 应用层 |
plugins | 插件聚合包 | 应用层 |
vscode-extension | VSCode 扩展 | 应用层 |
playground | 在线 playground | 应用层 |
test-utils | 测试工具库 | 应用层 |
lytjs | 聚合包,一次安装所有核心能力 | 应用层 |
二、环境搭建:五分钟搞定
前置要求
| 工具 | 版本要求 | 说明 |
|---|---|---|
| Node.js | >= 18.0.0 | 必需 |
| Git | 最新版 | 必需 |
| pnpm | 最新版 | 包管理器 |
| VSCode | 最新版 | 推荐,配合项目自带的 Trae AI 配置效果更佳 |
第一步:Fork & Clone
# 1. Fork 主仓库到你的 Gitee/GitHub 账号
# 主仓库: https://gitee.com/lytjs/lytjs
# 镜像仓库: https://github.com/idcu/lytjs
# 2. 克隆你 Fork 的仓库
git clone https://gitee.com/<your-username>/lytjs.git
cd lytjs
# 3. 添加上游仓库(方便后续同步)
git remote add upstream https://gitee.com/lytjs/lytjs.git
第二步:安装依赖
pnpm install
项目使用 pnpm workspace 管理所有子包,一条命令即可安装全部依赖。
第三步:构建项目
pnpm build
构建脚本位于 scripts/build-all.sh,使用 esbuild 进行打包,速度极快。
第四步:运行测试
# 运行全部 2833+ 个测试用例
pnpm test
# 生成覆盖率报告
pnpm test:coverage
测试使用项目自定义的测试运行器(tests/test-runner.ts),配合 c8 生成覆盖率,jsdom 模拟 DOM 环境。
第五步:验证环境
# 运行 lint 检查
pnpm lint
# 运行基准测试(可选)
pnpm benchmark
如果你看到所有测试通过、lint 无错误,恭喜你 —— 开发环境已经就绪。
三、项目结构:快速导航
拿到代码后,第一件事是搞清楚文件在哪。以下是项目的完整目录结构:
lytjs/
├── packages/ # 32 个子包(核心!)
│ ├── core/ # 核心入口
│ ├── reactivity/ # 响应式系统
│ ├── compiler/ # 模板编译器
│ ├── renderer/ # 渲染器(DOM/SSR/Vapor)
│ ├── component/ # 组件系统
│ ├── vdom/ # 虚拟 DOM
│ ├── common/ # 公共工具
│ ├── router/ # 路由
│ ├── store/ # 状态管理
│ ├── components/ # UI 组件库(50+)
│ ├── cli/ # 命令行工具
│ ├── ai/ # AI 辅助开发
│ ├── compat/ # Vue 3 兼容层
│ ├── lytx/ # 元框架
│ ├── devtools/ # 浏览器开发者工具
│ ├── micro-frontend/ # 微前端
│ ├── performance/ # 性能监控
│ ├── plugin-sdk/ # 插件开发 SDK
│ ├── plugin-registry/ # 插件注册中心
│ ├── plugin-auth/ # 认证插件
│ ├── plugin-chart/ # 图表插件
│ ├── plugin-highlight/ # 代码高亮插件
│ ├── plugin-i18n/ # 国际化插件
│ ├── plugin-logger/ # 日志插件
│ ├── plugin-storage/ # 存储插件
│ ├── plugin-theme/ # 主题插件
│ ├── plugin-virtual-list/# 虚拟列表插件
│ ├── plugins/ # 插件聚合包
│ ├── vscode-extension/ # VSCode 扩展
│ ├── playground/ # 在线 playground
│ └── test-utils/ # 测试工具库
├── docs/ # VitePress 文档站
│ ├── guide/ # 用户指南(19 个文档)
│ ├── api/ # API 参考(12 个文档)
│ ├── developer/ # 开发者文档
│ └── en/ # 英文文档(12 个文档)
├── benchmarks/ # 性能基准测试
├── examples/ # 12 个示例项目
├── scripts/ # 构建/发布脚本
├── blog/ # 技术博客(10 篇)
├── templates/ # 项目模板
├── .trae/ # Trae AI IDE 配置
├── eslint.config.js # ESLint 配置
├── tsconfig.json # TypeScript 根配置
├── llms.txt # AI 文档(供 LLM 使用)
├── llms-full.txt # AI 文档完整版
└── CHANGELOG.md # 变更日志
每个子包的内部结构
所有子包遵循统一的目录规范:
packages/<package-name>/
├── src/ # 源码
│ ├── index.ts # 统一入口(只做导出)
│ └── ... # 具体实现
├── __tests__/ # 测试
│ ├── <name>.test.ts # 单元测试
│ └── <name>-edge-cases.test.ts # 边界测试
├── dist/ # 构建输出
├── package.json # 包配置
├── tsconfig.json # TypeScript 配置
└── README.md # 包文档
四、代码规范:写出符合项目风格的代码
Lyt.js 对代码质量有明确要求。以下规则由 ESLint 强制执行,CI 流水线会自动检查。
TypeScript 配置
{
"compilerOptions": {
"strict": true,
"target": "ES2018",
"module": "ESNext",
"moduleResolution": "bundler"
}
}
项目启用了 TypeScript 严格模式,这意味着:
noImplicitAny—— 禁止隐式 anystrictNullChecks—— 严格的 null 检查strictFunctionTypes—— 严格的函数类型检查
ESLint 核心规则
| 规则 | 配置 | 示例 |
|---|---|---|
| 引号 | 单引号 | const msg = 'hello' |
| 缩进 | 2 空格 | if (x) { |
| 分号 | 必须使用 | const a = 1; |
| 尾逗号 | 多行时必须(数组、对象、导入、导出) | { a: 1, b: 2, } |
| 函数尾逗号 | 不使用 | function foo(a, b) {} |
prefer-const | 推荐 | 能用 const 就不用 let |
no-explicit-any | error | 禁止使用 any 类型 |
| 未使用变量 | 下划线 _ 开头允许 | const _unused = 1 |
编码注意事项
这些是项目特别强调的编码规范:
- 文件编码:UTF-8,不要使用 GBK
- 不要添加 BOM:文件开头不要有 BOM 标记
- 中文标点:中文内容使用全角标点符号(,。!?)
- 换行符:LF(Unix 风格)
- 行尾:文件末尾保留一个空行
项目提供了编码检查工具:
pnpm docs:check-encoding
代码风格示例
// ✅ 正确的代码风格
import { reactive, effect } from '@lytjs/reactivity';
const state = reactive({
count: 0,
name: 'Lyt.js',
});
effect(() => {
console.log('count:', state.count);
});
// ❌ 错误的代码风格
import { reactive, effect } from "@lytjs/reactivity"
const state = reactive({count:0,name:"Lyt.js"})
命名规范
| 类型 | 风格 | 示例 |
|---|---|---|
| 文件名 | kebab-case | html-parser.ts、create-app.ts |
| 变量/函数 | camelCase | userName、getUserInfo() |
| 类/接口 | PascalCase | ReactiveEffect、UserInfo |
| 常量 | UPPER_SNAKE_CASE | MAX_COUNT、API_BASE_URL |
| 私有成员 | 下划线前缀 | _privateProp、_privateMethod() |
五、开发流程:从 Issue 到 PR
分支策略
Lyt.js 使用 develop 作为主开发分支:
develop(主开发分支)
├── feat/xxx 功能分支
├── fix/xxx 修复分支
├── docs/xxx 文档分支
├── refactor/xxx 重构分支
├── perf/xxx 性能优化分支
└── test/xxx 测试分支
完整工作流
Step 1:同步最新代码
git checkout develop
git pull upstream develop
Step 2:创建功能分支
git checkout -b feat/reactivity-watch-flush
分支命名规范:<type>/<scope>-<description>
| 前缀 | 用途 | 示例 |
|---|---|---|
feat/ | 新功能 | feat/core-error-boundary |
fix/ | Bug 修复 | fix/reactivity-nested-computed |
docs/ | 文档更新 | docs/component-api |
refactor/ | 代码重构 | refactor/renderer-patch |
perf/ | 性能优化 | perf/vdom-diff |
test/ | 测试相关 | test/compiler-edge-cases |
Step 3:开发与测试
编写代码,同时编写对应的测试用例:
# 运行测试
pnpm test
# 运行 lint
pnpm lint
# 自动修复 lint 问题
pnpm lint:fix
Step 4:提交代码
项目遵循 Conventional Commits 规范:
<type>(<scope>): <subject>
提交类型:
| type | 说明 | 示例 |
|---|---|---|
feat | 新功能 | feat(core): 添加 createApp 错误边界支持 |
fix | 修复 Bug | fix(reactivity): 修复嵌套 computed 循环依赖检测 |
docs | 文档变更 | docs(components): 更新 Button 组件 API 文档 |
style | 代码格式 | style: 统一缩进为 2 空格 |
refactor | 重构 | refactor(renderer): 重构 patch 算法 |
perf | 性能优化 | perf(renderer): 优化 DOM diff 算法性能 |
test | 测试相关 | test(reactivity): 添加 signal 边界测试 |
chore | 构建/工具 | chore: 更新 TypeScript 到 6.0 |
scope 对应包名:core、reactivity、compiler、renderer、component、components、router、store、cli、devtools、lytx、ai、common。
Step 5:添加变更记录
pnpm changelog:add
Step 6:推送并创建 PR
git push origin feat/reactivity-watch-flush
然后在 Gitee 或 GitHub 上创建 Pull Request,目标分支为 develop。
六、常用开发命令速查
以下是 package.json 中定义的所有开发命令:
| 命令 | 说明 |
|---|---|
pnpm build | 构建所有包 |
pnpm test | 运行全部测试 |
pnpm test:coverage | 生成测试覆盖率报告 |
pnpm lint | ESLint 检查 |
pnpm lint:fix | ESLint 自动修复 |
pnpm benchmark | 响应式系统基准测试 |
pnpm benchmark:vapor | Vapor 模式基准测试 |
pnpm benchmark:vdom | 虚拟 DOM 基准测试 |
pnpm benchmark:all | 运行全部基准测试 |
pnpm clean | 清理构建产物 |
pnpm clean:temp | 清理临时文件 |
pnpm version:check | 检查当前版本 |
pnpm version:set | 设置版本号 |
pnpm version:bump:patch | 升级补丁版本 |
pnpm version:bump:minor | 升级次版本 |
pnpm changelog | 查看变更日志 |
pnpm changelog:add | 添加变更记录 |
pnpm changelog:preview | 预览变更日志 |
pnpm changelog:release | 发布版本时生成变更日志 |
pnpm docs:check-encoding | 检查文件编码 |
pnpm publish:dry-run | 发布预演(不实际发布) |
pnpm publish:all | 发布所有包 |
七、阅读源码:推荐路径
面对 91,227 行源码,从哪里开始?以下是我推荐的阅读路径。
入门路径:理解核心机制
1. packages/reactivity/src/effect.ts ← 一切的起点
2. packages/reactivity/src/reactive.ts ← Proxy 代理实现
3. packages/reactivity/src/ref.ts ← Ref 实现
4. packages/reactivity/src/computed.ts ← 计算属性
5. packages/reactivity/src/watch.ts ← 侦听器
6. packages/reactivity/src/signal.ts ← Signal 模式
为什么从 reactivity 开始? 因为它是整个框架的基石。renderer、component、router、store 全部依赖它。理解了 reactivity,你就理解了框架 50% 的核心逻辑。
进阶路径:理解编译与渲染
7. packages/compiler/src/parser/html-parser.ts ← HTML 解析器
8. packages/compiler/src/transform/transform.ts ← AST 转换
9. packages/compiler/src/codegen/codegen.ts ← 代码生成
10. packages/vdom/src/vnode.ts ← 虚拟节点
11. packages/vdom/src/patch.ts ← Diff 算法
12. packages/renderer/src/dom/dom-renderer.ts ← DOM 渲染器
高级路径:理解组件与生态
13. packages/component/src/define-component.ts ← 组件定义
14. packages/component/src/lifecycle.ts ← 生命周期
15. packages/core/src/create-app.ts ← 应用创建
16. packages/router/src/create-router.ts ← 路由系统
17. packages/store/src/create-store.ts ← 状态管理
配套资源
| 资源 | 位置 | 说明 |
|---|---|---|
| 开发者文档 | docs/developer/ | 架构总览、入门指南、代码规范 |
| API 文档 | docs/api/ | 12 个 API 参考文档 |
| 用户指南 | docs/guide/ | 19 个用户指南文档 |
| 英文文档 | docs/en/ | 12 个英文文档 |
| 技术博客 | blog/ | 10 篇深度技术文章 |
| AI 文档 | llms.txt / llms-full.txt | 供 AI 工具使用的项目文档 |
| 示例项目 | examples/ | 12 个可运行的示例 |
八、测试:2833+ 个用例守护质量
Lyt.js 拥有 46,212 行测试代码,分布在 78 个测试文件中,覆盖 2833+ 个测试用例。
测试框架
- 测试运行器:项目自定义(
tests/test-runner.ts) - 测试工具:
@lytjs/test-utils - 覆盖率工具:c8
- DOM 模拟:jsdom
- 无障碍测试:axe-core
测试文件位置
packages/<package-name>/__tests__/
├── <name>.test.ts # 主测试
├── <name>-edge-cases.test.ts # 边界测试
└── <name>-integration.test.ts # 集成测试
测试编写示例
import { reactive, effect } from '../src';
describe('reactivity', () => {
describe('reactive', () => {
it('should create a reactive proxy', () => {
const state = reactive({ count: 0 });
expect(state).toBeDefined();
});
it('should trigger effect on change', () => {
const state = reactive({ count: 0 });
let dummy;
effect(() => {
dummy = state.count;
});
state.count++;
expect(dummy).toBe(1);
});
});
});
测试原则
- 为新功能编写测试 —— 每个新功能必须附带测试用例
- 为 Bug 修复编写回归测试 —— 防止问题再次出现
- 覆盖三种场景 —— 正常路径、边界情况、错误处理
- Mock 外部依赖 —— 保持测试的独立性和可重复性
- 核心包保持高覆盖率 —— core、reactivity、renderer、compiler 尤其重要
九、版本发布流程
了解发布流程,有助于你理解 PR 合并后的完整生命周期:
1. pnpm test ← 确保所有测试通过
2. pnpm version:bump:patch ← 升级版本号
(或 minor / major)
3. pnpm changelog:release ← 生成变更日志
4. pnpm build ← 构建所有包
5. pnpm test && pnpm lint ← 最终验证
6. pnpm publish:dry-run ← 发布预演
7. pnpm publish:all ← 正式发布
发布脚本位于 scripts/ 目录:
| 脚本 | 职责 |
|---|---|
scripts/build-all.sh | 构建所有包 |
scripts/build.js | Node.js 构建脚本 |
scripts/version.js | 版本号管理 |
scripts/changelog.js | 变更日志生成 |
scripts/publish.sh | 发布到 npm |
scripts/pack.js | 打包 |
scripts/size-report.js | 体积报告 |
十、PR 检查清单:提交前必读
在提交 PR 之前,逐项确认以下清单:
- 构建通过:
pnpm build成功 - 测试通过:
pnpm test全部通过 - Lint 通过:
pnpm lint无错误 - 文档已更新:公共 API 变更已更新对应文档
- CHANGELOG 已添加:使用
pnpm changelog:add添加变更记录 - 编码检查通过:文件编码为 UTF-8 无 BOM(
pnpm docs:check-encoding) - 提交信息规范:遵循 Conventional Commits 规范
- PR 标题清晰:使用 Conventional Commits 格式
- 关联 Issue:PR 描述中使用
Fixes #xxx或Closes #xxx - 破坏性变更已标注:如有 breaking change,在 PR 描述中明确说明
十一、贡献方式:不只是写代码
成为核心贡献者不只有写代码这一条路。Lyt.js 欢迎以下形式的贡献:
适合新手的任务
| 贡献类型 | 难度 | 说明 |
|---|---|---|
| 修复文档错别字 | 入门 | 发现文档中的错误,直接提 PR |
| 补充 API 文档 | 入门 | 为缺少文档的 API 编写说明 |
| 添加测试用例 | 初级 | 为现有功能补充边界测试 |
| 修复已知 Bug | 初级 | 从 Issues 中认领 Bug |
| 翻译文档 | 初级 | 将中文文档翻译为英文(docs/en/) |
适合进阶的任务
| 贡献类型 | 难度 | 说明 |
|---|---|---|
| 新增 UI 组件 | 中级 | 在 packages/components/ 中添加新组件 |
| 开发新插件 | 中级 | 基于 plugin-sdk 开发功能插件 |
| 优化性能 | 中级 | 使用 pnpm benchmark 发现并优化性能瓶颈 |
| 完善示例项目 | 中级 | 在 examples/ 中添加新的示例 |
适合高级的任务
| 贡献类型 | 难度 | 说明 |
|---|---|---|
| 核心模块优化 | 高级 | 优化 reactivity/compiler/renderer 的核心算法 |
| 新渲染器开发 | 高级 | 开发小程序渲染器、移动端渲染器 |
| 元框架功能 | 高级 | 扩展 lytx 的 SSR/SSG 能力 |
| AI 集成增强 | 高级 | 增强 packages/ai/ 的 AI 辅助能力 |
十二、文档体系:在哪里写文档
Lyt.js 拥有完善的文档体系,了解文档位置有助于你做出精准的贡献:
| 文档类型 | 位置 | 数量 |
|---|---|---|
| 用户指南 | docs/guide/ | 19 个文档 |
| API 参考 | docs/api/ | 12 个文档 |
| 开发者文档 | docs/developer/ | 含架构总览、入门指南、代码规范 |
| 英文文档 | docs/en/ | 12 个文档 |
| 变更日志 | CHANGELOG.md | 项目级变更日志 |
| AI 文档 | llms.txt / llms-full.txt | 供 LLM 使用 |
| 包文档 | packages/*/README.md | 各包独立说明 |
| 技术博客 | blog/ | 10 篇深度文章 |
注意:公共 API 变更时,需要同步更新
llms.txt和llms-full.txt,确保 AI 工具(如 Cursor、Trae)能获取到最新的 API 信息。
十三、社区与沟通
仓库地址
| 平台 | 地址 | 用途 |
|---|---|---|
| Gitee(主仓库) | gitee.com/lytjs/lytjs | 国内开发者,Issue、PR |
| GitHub(镜像) | github.com/idcu/lytjs | 海外开发者,自动同步 |
参与方式
- Bug 报告:在 Gitee 或 GitHub 提交 Issue,使用模板填写复现步骤
- 功能建议:提交 Feature Request Issue,描述使用场景和期望行为
- 代码贡献:Fork → 开发 → 提 PR → 代码审查 → 合并
- 代码审查:帮助审查其他人的 PR,也是重要的贡献方式
Issue 模板
项目提供了四种 Issue 模板:
bug_report.md—— Bug 报告feature_request.md—— 功能建议question.md—— 提问config.yml—— Issue 自动标签配置
十四、从第一行代码到核心贡献者
最后,分享一条从新手到核心贡献者的成长路径:
第一阶段:熟悉项目(1-2 周)
- 克隆仓库,搭建开发环境
- 通读
docs/developer/下的开发者文档 - 运行测试,理解测试结构
- 从 reactivity 包开始阅读源码
- 修复一个文档问题或补充一个测试用例
第二阶段:小规模贡献(2-4 周)
- 认领一个标记为
good first issue的 Bug - 为某个功能补充边界测试
- 添加或完善一个 UI 组件
- 提交 3-5 个被合并的 PR
第三阶段:深度参与(1-3 个月)
- 参与核心模块的代码审查
- 提出架构优化建议
- 开发新插件或新功能
- 撰写技术博客(
blog/目录) - 帮助回答社区问题
第四阶段:核心贡献者(持续)
- 主导一个子模块的开发和维护
- 参与版本发布流程
- 指导新贡献者
- 参与项目方向讨论
写在最后
Lyt.js 是一个 137,439 行 TypeScript、零运行时依赖、32 个子包 的完整前端框架。它有清晰的架构、严格的代码规范、完善的测试覆盖和详尽的文档体系。
无论你是想学习框架内部原理、提升 TypeScript 能力,还是单纯想为开源社区做贡献,Lyt.js 都是一个值得投入的项目。
从克隆仓库开始,从修复一个文档错别字开始,从补充一个测试用例开始。 每一个贡献都有价值。
「轻写轻跑,所见即代码」—— Lyt.js
期待在贡献者列表中看到你的名字。
| 项目信息 | |
|---|---|
| 主仓库 | gitee.com/lytjs/lytjs |
| 镜像仓库 | github.com/idcu/lytjs |
| 许可证 | MIT |
| 当前版本 | v5.0.1 |