HelloWorld 扩展开发教程
做一个 HelloWorld 扩展,核心步骤很直接:选定目标平台(比如浏览器、编辑器或 Node 原生模块),搭建最小可运行单元(manifest/入口、事件处理、简单 UI),运行并调试,最后打包发布。下面我会以实操为主线,逐步拆解浏览器扩展、VS Code 插件和 Node 原生 addon 的从零到可运行示例,解释每一步背后的原理和常见坑,带点生活化的讲解,方便你照着做并快速定位问题。

先弄清楚“扩展”到底是什么
想像一下扩展就是给主应用“贴个便签”或“加个小零件”。它不是重写主程序,而是通过约定的接口和入口,插入少量功能:在浏览器里可能是按钮或脚本,在编辑器里是命令或侧边视图,在 Node 里是一个可以被 require 的二进制模块。关键概念有三项:入口(entry)、权限/API(capabilities)、和 生命周期(lifecycle)。
通用准备工作与工具
- 代码编辑器:VS Code(大多数示例用它),或你习惯的编辑器。
- Node.js 与 npm:用于构建、打包、测试。
- 浏览器:Chrome 或 Chromium 系列用于加载开发版扩展;Edge 类似。
- 调试工具:浏览器 DevTools、VS Code 的 Extension Host 调试功能、node-gyp 的调试输出。
- 版本控制:git,便于回滚和发布记录。
关键术语速记(用费曼法解释)
- Manifest:像身份证,声明扩展名字、权限、入口文件。
- Background / Service Worker:常驻或事件驱动的后台脚本,处理长期任务或消息。
- Content Script:注入到页面的脚本,用来读写页面 DOM。
- Activation Events(编辑器插件):何时加载插件,节省资源。
- Bindings / N-API(Node 原生):让 C/C++ 代码和 JS 互相调用的桥梁。
案例一:Chrome 浏览器扩展(Manifest V3)HelloWorld
这里做一个最小可运行的浏览器扩展:右上角有个工具栏按钮,点了弹出一个简单的 popup,并在当前页面插入一句话。
项目文件结构
| 文件名 | 说明 |
| manifest.json | 扩展声明(权限、入口) |
| background.js | 事件脚本(MV3 多用 service worker) |
| popup.html | 工具栏弹出页面 |
| content.js | 注入到网页的脚本 |
| icons/ | 图标资源 |
示例 manifest.json(最小)
{
"manifest_version": 3,
"name": "HelloWorld Demo",
"version": "1.0",
"action": {
"default_popup": "popup.html",
"default_icon": { "16": "icons/16.png" }
},
"background": {
"service_worker": "background.js"
},
"permissions": ["scripting", "activeTab"]
}
background.js(简单事件监听)
chrome.action.onClicked.addListener((tab) => {
// 不一定需要,示例说明如何调用 scripting
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ['content.js']
});
});
popup.html(简单 UI)
<!doctype html>
<meta charset="utf-8">
<button id="say">在页面插入 HelloWorld
content.js(注入页面)
const el = document.createElement('div');
el.textContent = 'HelloWorld from extension';
el.style.position = 'fixed';
el.style.bottom = '10px';
el.style.right = '10px';
el.style.background = 'rgba(0,0,0,0.7)';
el.style.color = '#fff';
el.style.padding = '6px 10px';
el.style.borderRadius = '4px';
document.body.appendChild(el);
调试与发布要点
- Chrome 地址栏输入 chrome://extensions,开启“开发者模式”,加载已解压的扩展。
- 检查后台(service worker)在扩展页面的“背景页”里可见日志。
- 权限尽量少请求:只在需要时请求 activeTab 或 scripting,以提高审查通过率。
- 发布到 Chrome Web Store 需要支付开发者注册费并通过审查。
案例二:VS Code 插件 HelloWorld(TypeScript)
VS Code 插件通常是用 TypeScript 写然后编译成 JavaScript,插件通过 VS Code 的 API 注册命令、面板或语言支持。先教最简单的“弹一个信息框”的命令。
核心文件与说明
- package.json:声明扩展元信息、激活事件与命令。
- src/extension.ts:扩展入口,导出 activate 和 deactivate。
- tsconfig.json:TypeScript 配置。
package.json(关键片段)
{
"name": "helloworld-demo",
"displayName": "HelloWorld Demo",
"publisher": "you",
"engines": { "vscode": "^1.60.0" },
"activationEvents": ["onCommand:helloworld.start"],
"contributes": {
"commands": [{
"command": "helloworld.start",
"title": "HelloWorld: Say Hello"
}]
},
"main": "./out/extension.js",
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./"
},
"devDependencies": { "@types/vscode": "^1.60.0", "typescript": "^4.0.0" }
}
src/extension.ts(核心逻辑)
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
const disposable = vscode.commands.registerCommand('helloworld.start', () => {
vscode.window.showInformationMessage('Hello from HelloWorld extension!');
});
context.subscriptions.push(disposable);
}
export function deactivate() {}
运行与发布
- 在 VS Code 中按 F5,会打开一个 Extension Development Host,运行你的插件。
- 用 vsce 打包并发布到 Visual Studio Marketplace(需要 publisher 设置与 PAT)。
- 注意 activationEvents,不要在不必要场景激活扩展,以免影响性能。
案例三:Node.js 原生扩展(N-API 简易示例)
当你需要把性能敏感或已有 C/C++ 代码暴露给 Node 时,可以写原生 addon。下面示例用 N-API 创建一个导出 hello() 的模块。
文件结构与说明
| 文件 | 作用 |
| binding.gyp | 构建配置(node-gyp) |
| hello.cpp | C++ 源文件,用 N-API 实现方法 |
| index.js | 封装并导出模块接口 |
binding.gyp(最小)
{
"targets": [{
"target_name": "hello",
"sources": [ "hello.cpp" ],
"cflags_cc": [ "-std=c++17" ]
}]
}
hello.cpp(N-API)
#include <napi.h>
Napi::String Hello(const Napi::CallbackInfo& info) {
return Napi::String::New(info.Env(), "Hello from native addon");
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set("hello", Napi::Function::New(env, Hello));
return exports;
}
NODE_API_MODULE(hello, Init)
index.js(使用 native addon)
const hello = require('bindings')('hello'); // 或 require('./build/Release/hello')
console.log(hello.hello());
构建与注意点
- 安装 node-gyp 和编译工具链(Windows 需要 windows-build-tools,Linux/macOS 需要 make/gcc/clang)。
- 运行:node-gyp configure build。
- 关注 Node、N-API 和编译器版本兼容性,N-API 目标尽量使用稳定接口。
常见问题与调试技巧(跨平台通用)
- 扩展不生效:先看日志,浏览器看扩展页的错误控制台,VS Code 查看开发主机的输出,Node 看构建错误。
- 权限/激活时机:过度权限会被拒,激活事件要精简,延迟加载能提升主应用性能。
- 跨域或 CSP:内容脚本在页面上有 CSP 限制,尽量在扩展自身页面或通过 messaging 与 content script 交互。
- 版本兼容:manifest v2 已被弃用,注意使用目标平台当前推荐的 API(例如 Chrome 的 MV3)。VS Code API 随版本变动,要指定 engines。
- 本地化:将可见文本放入语言文件(_locales 或 package.nls.json),便于后续翻译和国际化。
一个对比表,帮助你决定从哪里开始
| 平台 | 典型用途 | 学习曲线 |
| 浏览器扩展 | 界面增强、自动化、脚本注入 | 低 - 中 |
| VS Code 插件 | 编辑器命令、语言支持、视图扩展 | 中 |
| Node 原生 addon | 性能敏感任务、复用 C/C++ 库 | 高 |
实战小贴士(边做边学的那些事)
- 从最小可运行版本开始:先能弹窗、先能在页面显示一句话,再慢慢加复杂逻辑。
- 把常见功能写成小函数并做单元测试(VS Code 可用 mocha,Node 用 jest/mocha)。
- 遇到权限或 CSP 卡住时,回退到“控制台打印”法——在每个关键点打日志,追踪流程。
- 阅读官方文档是必须的,但不要被例子吓住:照抄例子能快速起步,理解原理再改造。
- 代码风格和发布前的清单(如隐私声明、截图、权限说明)往往决定审核是否一次通过。
补充:如何把 HelloWorld 变成可复用的模板
把公共逻辑抽成脚手架(脚本创建基本目录结构、填充 manifest/package、加入 CI 流程),能大幅提升后续效率。我常用的做法是把扩展分层:
- 核心逻辑层:业务函数,尽量纯函数,易测试。
- 适配层:把平台 API 的调用集中在一处,便于替换或模拟。
- UI 层:Popup、panel 或页面注入的 DOM 代码,保持轻量。
最后,别怕失败——扩展开发常常靠反复试错。你会发现第一次完整把 HelloWorld 从“不会”推进到“能运行”往往只需要几小时,但过程中你学到的调试与打包知识,会在后续项目里一直派上用场。顺便记一条经验:越早把东西做到可视化(弹窗或页面注入),越容易判断逻辑是否正确,调试效率会高很多。