每一个 VS Code 扩展都从一个 package.json 文件开始。这个文件不仅是 Node.js 项目的身份证,更是扩展向 VS Code 声明自己存在的方式。这一课我们以 claude-context-bar 的真实代码为标本,解剖扩展的骨架。
VS Code 本身是用 Electron(Chromium + Node.js)构建的。一个扩展就是一个在 VS Code 进程内运行的 Node.js 程序,它通过 VS Code Extension API(一个名为 vscode 的模块)与编辑器交互。
扩展能做的事情包括但不限于:
claude-context-bar 的做法)claude-context-bar 只用了 VS Code Extension API 的一小部分——状态栏、配置、文件监听和命令注册。这正是它作为入门学习标本的价值:复杂度可以被完全掌控。
打开 temp_repo/package.json,你会看到它是一个标准的 npm package.json,但多了几个 VS Code 扩展特有的字段。让我们逐段解剖:
// 这些是所有 npm 包都有的标准字段 "name": "claude-context-bar", // npm 包名(全小写,短横线分隔) "displayName": "Claude Context Bar", // 在 VS Code 扩展面板中显示的人类可读名称 "description": "Real-time context...", // 一句话描述 "version": "1.4.1", // 语义化版本(SemVer) "publisher": "ezoosk", // VS Code Marketplace 发布者 ID "license": "MIT", "icon": "images/icon.png", // 扩展图标(Marketplace 展示用)
"name" 字段:"全小写,短横线分隔"其实是两件事——"全小写"是 npm registry 的强制规则(含大写字母的新包会被拒绝),而"短横线"是社区约定(_ 和 . 在包名内部也合法,只是不能放开头)。完整规则速查见 npm 包命名规则参考。
"publisher" 字段是 VS Code 扩展独有的。它必须匹配你在 VS Code Marketplace 上注册的发布者 ID。发布扩展时需要用到它。
"engines": { "vscode": "^1.74.0" // 扩展要求的最低 VS Code 版本 }, "activationEvents": [ "onStartupFinished" // 何时激活扩展 ],
engines.vscode 声明了兼容的最低 VS Code 版本。^1.74.0 表示需要 1.74.0 或更高版本(但不能是 2.0)。
^(caret)是 npm semver 语法——它锁定最左非零段。^1.74.0 中 1 是第一段非零数字,所以 major 被锁定,覆盖范围是 >=1.74.0 <2.0.0。主版本号变化意味着不兼容的 API 变更,自动排除。完整 SemVer 语法速查 →
activationEvents 是关键的性能机制:它告诉 VS Code 什么时候才加载你的扩展。常见的激活事件有:
| 激活事件 | 含义 |
|---|---|
| onStartupFinished | VS Code 启动完成后立即激活(本扩展使用这个) |
| onCommand:xxx | 用户首次执行某个命令时激活(延迟加载) |
| onLanguage:python | 打开特定语言的文件时激活 |
| * | VS Code 一启动就激活(不推荐,影响启动性能) |
onStartupFinished 而不是 *?因为它需要在状态栏显示信息,但又不想拖慢 VS Code 的启动速度。onStartupFinished 是两全之策——等编辑器就绪后再初始化,不影响用户的启动体验。
"main": "./out/extension.js", // 扩展的 JavaScript 入口(编译产物)
这是 VS Code 加载扩展时执行的第一个文件。注意路径是 ./out/ 而不是 ./src/——因为 TypeScript 必须先编译成 JavaScript。VS Code 的 Node.js 环境不直接运行 TypeScript。
VS Code 要求这个文件导出一个 activate 函数和一个可选的 deactivate 函数。
"contributes": { "configuration": { "title": "Claude Context Bar", "properties": { "claudeContextBar.autoColor": { "type": "boolean", "default": true, "description": "..." } // ... 更多配置项 } } }
contributes 是扩展向 VS Code 注入能力的方式。claude-context-bar 只贡献了一种东西:用户配置项。每个配置项会自动出现在用户的 settings.json 中,提供自动补全和类型检查。
claudeContextBar.warningThreshold 为例:package.json)→ 定义类型、默认值、描述settings.json)→ 用户在 VS Code 设置面板中修改(不改则用默认值)extension.ts)→ vscode.workspace.getConfiguration('claudeContextBar').get('warningThreshold')number 类型不允许填字符串)、默认值回退、搜索和自动补全。这是 VS Code 声明式扩展模型的核心——扩展只声明自己需要什么,VS Code 负责呈现和管理。
扩展可以贡献的其他东西(本扩展没用到,但你将来可能用到):
commands — 注册命令到命令面板keybindings — 注册快捷键menus — 向菜单添加项目views — 向侧边栏添加视图languages — 注册新的编程语言支持"scripts": { "vscode:prepublish": "npm run compile", // 发布前自动执行 "compile": "tsc -p ./", // 编译 TypeScript "watch": "tsc -watch -p ./", // 监听模式(开发时用) "package": "vsce package", // 打包为 .vsix "publish": "vsce publish" // 发布到 Marketplace }
vscode:prepublish 是一个约定脚本名称。当你运行 vsce publish 时,它会自动先执行这个脚本,确保发布的总是最新的编译产物。这是一个发布安全网——防止你忘了编译就把旧代码发出去。
现在打开 temp_repo/src/extension.ts,用 Ctrl+F 搜索以下内容,观察 package.json 中的声明如何在代码中落地:
export function activate — VS Code 加载扩展时调用的入口claudeContextBar.hideSession — 代码中注册的命令,对应点击状态栏的行为claudeContextBar — 代码中读取配置的前缀,对应 package.json 中的配置项StatusBarAlignment.Right — 状态栏位置控制如果我想让扩展只在用户打开 Python 文件时才加载(而不是 VS Code 启动时),应该把 activationEvents 改成什么?
package.json 中的 "main": "./out/extension.js" 指向编译产物。VS Code 要求这个文件导出什么函数?
vscode:prepublish 脚本的作用是什么?