ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

VSCode插件开发实战:在代码注释里看小说

VSCode插件开发实战:在代码注释里看小说 1. 为什么要做一个在代码注释里看小说的插件1.1 这个插件的核心玩法与解决的真实痛点先说清楚这个插件到底干了什么装进VSCode之后它能把你指定的一部小说文本以代码注释的形式“植入”当前打开的代码文件里。你正常写代码、看代码的时候注释区域会显示小说章节内容而且每一章都用醒目的装饰器渲染出来状态栏还会显示当前章节进度。别的同事路过你的屏幕只会以为你在认真读代码注释实际上你正在追更。这话听起来像开玩笑但我真把它做出来了。事情起因很简单——我每天有大量时间要盯着VSCode改代码手机放旁边看小说容易分神切浏览器又容易被截图发给Leader。于是我开始琢磨有没有一种方式让小说内容直接出现在编辑器里表面看起来非常像业务代码的注释这个需求说白了就是三个字伪装性。而代码注释恰好是天然的伪装载体。没有哪个开发会因为你盯着注释看就觉得你在摸鱼。于是“VSCode插件开发流程兼代码注释阅读小说插件发布”这个项目就这么立项了。这篇文章我打算写透两件事一是把从零开发一个VSCode插件的完整流程梳理清楚包括环境搭建、API选型、调试技巧、打包发布二是用我自己的这个“代码注释看小说”插件作为案例把每一步设计逻辑和踩过的坑都摊开讲。不管你是想开发正经的生产力工具还是纯粹觉得这个脑洞有意思想复刻一个都可以直接按着这篇文章操作。1.2 对比过其他摸鱼方案后为什么选择插件形式在正式动手之前我认真对比过几种在编辑器里看小说的路子。第一种是直接打开一个内置的Markdown预览把小说内容塞进一个临时文件里用快捷键切换预览。这个方案坏处太明显Markdown预览窗口一眼就能看出不是代码而且编辑器会多出一个文件标签反而暴露。第二种是改编辑器主题把小说文字渲染成类似背景或高亮的装饰性内容。问题是VSCode的主题机制对文本内容的控制力很弱你没法轻松做到按章节加载、翻页、进度显示这些交互功能。第三种是干脆用Webview做一个内置阅读器在编辑器里开一个网页面板。这个功能上最强但Webview面板在界面上太显眼了一打开就是一个浏览器窗口完全失去伪装的意义。综合下来装饰器Decoration加注释解析的方案最合适。装饰器可以在不修改文件真实内容的情况下给某段文字加上背景色、下划线、颜色等样式而且是动态渲染的。配合命令面板、快捷键和状态栏可以实现不看文件本身、直接阅读注释内容的效果。最妙的是我完全可以不把小说写进当前文件而是动态地把文本“投影”到行尾注释区域这样代码文件本身保持干净关闭插件就彻底消失。1.3 最终形态插件从安装到使用的完整流程先说最终效果方便你判断是否值得往下看安装插件后通过命令面板CtrlShiftP输入“Novel: 打开小说阅读模式”启动插件读取内置的小说文本文件按章节切分默认从第一章开始当前打开的代码文件每一行末尾会追加一行行注释注释内容是当前章节的一段文字使用快捷键 AltPageDown 或 AltPageUp 切换章节状态栏显示“第X章 / 共Y章”切换章节时装饰器重新渲染不需要修改文件本身也不会污染你的源码这个流程里涉及到的技术点包括VSCode扩展激活机制、命令注册、装饰器API、状态栏UI、非代码文件资源读取、VSIX打包与Marketplace发布。接下来我从最基础的开发环境开始讲一步步带你走到发布上线。2. 开始写代码前的准备环境、脚手架与插件的运行原理2.1 开发环境搭建的完整步骤开发VSCode插件本质上是在Node.js环境下写一个扩展程序所以最基础的环境要求是装了Node.js 16以上版本有VSCode编辑器本身用1.80以上版本低版本有些API不支持然后全局安装Yeoman和VSCode扩展生成器。npm install -g yo generator-code装好之后执行yo code脚手架会让你选择扩展类型我当时选的是“New Extension (TypeScript)”这一步会生成一个完整的插件工程包含src/extension.ts、package.json、tsconfig.json、.vscode/launch.json这些关键文件。这里有个细节很多人喜欢用JavaScript写插件图省事。我强烈建议用TypeScript因为VSCode扩展SDK的API类型定义非常完善写代码时IDE能给你完整的自动补全提示调试复杂对象时不至于全靠猜。生成完项目后进入目录直接按F5VSCode会弹出一个新的“Extension Development Host”窗口这就是你的插件调试环境。在这个新窗口里插件已经被加载你可以直接测试命令、装饰器等所有功能而不需要打包安装。如果你不想用脚手架也可以手动创建package.json和src/extension.ts但需要自己配置很多编译和调试参数。新手阶段直接用脚手架最稳等到后面熟了再手动改造。2.2 认识VSCode插件的大脑package.json关键字段VSCode插件本质上只是一个遵循特定目录结构的Node.js项目它和普通Node项目的最大区别就在于package.json里声明了一大堆VSCode扩展专用的字段。这些字段决定了插件何时被激活、提供了哪些命令、占用了哪些配置项。我先拆解一下最关键的一个字段activationEvents。这是插件的“开机密码”只有匹配到这些事件时VSCode才会去加载并运行你的插件代码。如果这个字段配置不对最常见的问题就是插件明明安装了但你调用的命令完全不存在。常见的激活事件有activationEvents: [ onCommand:novel.openReader, onLanguage:typescript ]onCommand:novel.openReader表示当用户执行名为novel.openReader的命令时激活插件。onLanguage:typescript表示只要打开TypeScript文件就激活。如果你希望插件在每次打开编辑器时都运行可以直接用一个数组把所有语言都列进去但我不建议这么干会拖慢编辑器启动速度浪费内存。第二个关键字段是contributes它用来往VSCode里“贡献”东西。最常用的是注册命令contributes: { commands: [ { command: novel.openReader, title: 小说阅读打开阅读模式, category: Novel }, { command: novel.nextChapter, title: 小说阅读下一章, category: Novel }, { command: novel.prevChapter, title: 小说阅读上一章, category: Novel } ], keybindings: [ { command: novel.nextChapter, key: altpagedown }, { command: novel.prevChapter, key: altpageup } ], configuration: { title: Novel Reader, properties: { novel.reader.novelFilePath: { type: string, default: , description: 小说文本文件路径留空则使用内置示例文本 } } } }这里我加了一个配置项novel.reader.novelFilePath允许用户指定自定义小说文件路径。因为在真实使用中内置文本容量有限且放到安装包里会让插件体积变大。更好的方案是让用户指定一个本地txt文件路径插件启动时去读取。最后是engines字段用来声明插件兼容的VSCode版本engines: { vscode: ^1.80.0 }这里有个大坑如果发布时engines版本范围写得太高老版本VSCode用户就装不上你的插件写得太低可能会用到更高版本才有的API导致用户运行时功能异常。我的做法是先按本机VSCode版本写一个范围比如^1.80.0然后再去查阅我用的API最低支持版本确保不高于1.80。2.3 调试环境与F5启动调试VSCode扩展的开发调试体验相当顺滑尤其适合新手。脚手架生成的项目里已经帮你配置好了.vscode/launch.json里面有两个主要的调试配置{ version: 0.2.0, configurations: [ { name: Run Extension, type: extensionHost, request: launch, args: [ --extensionDevelopmentPath${workspaceFolder} ] }, { name: Extension Tests, type: extensionHost, request: launch, args: [ --extensionDevelopmentPath${workspaceFolder}, --extensionTestsPath${workspaceFolder}/out/test/suite/index ] } ] }第一项“Run Extension”是最常用的。按下F5后VSCode会启动一个全新的窗口这个窗口自动加载了你正在开发的插件并且连接了调试器。你可以直接在extension.ts里打断点观察变量值也可以在这个窗口里操作插件、查看Output面板里的console日志。在你调试过程中有两个经常被忽略但很重要的技巧修改代码后直接按CtrlShiftF5可以快速重启扩展开发宿主窗口不用每次都F5重新启动。如果插件在激活时抛异常可以在调试控制台里看到完整堆栈定位问题很快。3. 核心功能实现如何让小说文本“伪装”成注释3.1 小说文本的存储方案与打包路径处理这个插件的核心素材是小说文本怎么存放它决定了后续所有解析逻辑的难易程度。我试过三种方式最后选定了一种最稳的。第一种是直接把小说文本硬编码成TypeScript字符串。这个方案最简单但只适合非常短的文本。一旦文本超过几百行字符串拼起来又乱又容易出转义问题完全没有维护性。第二种是作为插件安装包内的资源文件放在resources/novel.txt通过扩展上下文API读取。这个方案最大的好处是插件发布后全部内容都打包进VSIX用户不需要额外放置任何文件开箱即用。我当时决定内置一小段公版短篇作为演示同时还支持用户通过配置指定自己的小说文件。读取安装包内资源的代码如下export function getNovelContent(context: vscode.ExtensionContext): string { const filePath vscode.Uri.joinPath(context.extensionUri, resources, novel.txt); const content fs.readFileSync(filePath.fsPath, utf-8); return content; }这里有个关键点在开发调试时context.extensionUri指向你的项目根目录可以直接读到resources下的文件但打包安装后这个路径指向的是~/.vscode/extensions/xxx/下的安装目录同样是相对路径。所以只要你的文件在发布时被打包进去路径逻辑就完全一致。但这里有个发布时容易踩的坑vsceVSCode扩展打包工具默认会忽略一些文件比如.vscode、node_modules里的大部分内容、图片之外的二进制文件等。如果你的novel.txt放在resources目录下vsce是默认会包含的但如果你放在别的自定义目录需要在.vscodeignore文件里明确排除掉不该打包的东西。我遇到过打包后插件体积正常但运行时却读不到txt文件的情况最后排查发现是vsce没有把txt文件打进去。想知道哪些文件会被打包执行vsce ls命令即可查看包内清单。3.2 注释解析器的实现行注释、块注释与转义为了把小说内容“伪装”成注释我需要一个注释解析器。最直接的思路是只处理行注释也就是//后面的内容。因为VSCode里的每种编程语言都定义了行注释符号比如JavaScript、TypeScript、Java、Go都是//Python是#SQL是两个连字符--HTML是!--。所以我需要判断当前打开的文件属于哪种语言然后取出对应的行注释前缀。VSCode提供了一种语言配置能力可以通过Languages扩展点获取注释定义但更简单的方式是直接内置一个语言到注释符号的映射表const lineCommentMap: Recordstring, string { javascript: //, typescript: //, python: #, java: //, go: //, rust: //, sql: --, html: !--, css: /*, scss: //, c: //, cpp: //, csharp: // };拿到注释前缀后把小说文本的每一行都加上前缀然后拼接到当前文件每一行的行尾。这里有一个需要重点处理的问题注释文本里如果包含了换行符怎么办因为装饰器是按行渲染的一行范围内无法显示真正的换行。我的方案是把小说按段落切分每一段在展示时用两个空格夹住段首段尾不做硬换行。还有一个更隐蔽的问题小说文本里如果本身含有*/这样的字符串在某些语言比如CSS里可能会意外关闭块注释。虽然我主要用的是行注释但为了稳妥在拼接到行尾之前我会先做一次字符串清洗把常见的注释敏感字符做转义处理function sanitizeForComment(text: string, commentPrefix: string): string { // 替换可能破坏注释结构的字符 // 比如在CSS块注释里需要防止 */ // 在行注释里需要防止换行符 return text .replace(/\r?\n/g, ) .replace(/\*\//g, * /) .replace(/\/\*/g, / *); }3.3 用装饰器在编辑器中渲染章节内容注释解析只是解决了“文本怎么放到注释里”的问题真正让注释“看起来像阅读器”的效果靠的是VSCode的装饰器API。装饰器可以给编辑器里的某个文本范围附加CSS样式比如前景色、背景色、加粗、斜体、下划线等。它和直接修改文件内容最大的区别是装饰器是纯渲染层的不改变文件保存后的内容关闭插件后效果自动消失不会污染源码。注册装饰器类型的代码const titleDecoration vscode.window.createTextEditorDecorationType({ color: #e67e22, fontWeight: bold, fontSize: 1.05em, isItalic: true }); const contentDecoration vscode.window.createTextEditorDecorationType({ color: #2c3e50, fontStyle: italic, backgroundColor: rgba(255, 255, 200, 0.2) });然后在每次切换章节时计算当前文件每一行的行尾位置生成一个Range数组传给editor.setDecorations方法function renderChapterInFile(editor: vscode.TextEditor, lines: string[], chapterTitle: string) { const titleRanges: vscode.Range[] []; const contentRanges: vscode.Range[] []; lines.forEach((lineText, index) { const line editor.document.lineAt(index); const position line.range.end; if (index 0) { // 第一行追加章节标题 titleRanges.push(new vscode.Range(position, position.translate(0, chapterTitle.length 3))); } else { contentRanges.push(new vscode.Range(position, position.translate(0, lineText.length 3))); } }); editor.setDecorations(titleDecoration, titleRanges); editor.setDecorations(contentDecoration, contentRanges); }注意我生成Range时用的坐标是从行尾往后偏移这意味着我并没有真正在文件里插入任何字符但装饰器却能在视觉上“画出”文字。这里有个限制装饰器只能对实际存在的文本起作用。如果文件本身没有这一段内容Range对应的文本为空装饰器是无法凭空渲染出内容来的。所以这里必须改变思路装饰器不是用来“创建”文字而是用来给已经存在的内容加样式。真要实现“注释里显示小说”必须把小说文本实际追加到代码文件的每行末尾。也就是说我会先通过一个TextEdit操作把带有注释前缀的小说内容真正插入到文件每一行的行尾然后再用装饰器把标题和正文样式渲染出来。这种方式有一个取舍代码文件真的会被修改哪怕只是行尾追加注释。我接受的方案是在启动阅读模式之前先记录当前文件的快照退出阅读模式时用TextEdit把追加的内容全部删掉恢复原样。这样既能在阅读过程中享受装饰器带来的样式增强又能在不使用时保证文件干净。3.4 命令、快捷键与状态栏完整的交互闭环文本解析和渲染都搞定后还差一个交互层。我总共注册了三个命令novel.openReader打开阅读模式读取小说文件渲染第一章novel.nextChapter切换到下一章novel.prevChapter切换到上一章novel.closeReader退出阅读模式恢复文件原始内容在activate函数里注册命令的代码长这样export function activate(context: vscode.ExtensionContext) { let currentChapter 1; let totalChapters 1; let chapterLines: string[][] []; let novelContent ; let activeEditor: vscode.TextEditor | null null; const openReaderCommand vscode.commands.registerCommand(novel.openReader, async () { const editor vscode.window.activeTextEditor; if (!editor) { vscode.window.showErrorMessage(请先打开一个代码文件); return; } activeEditor editor; novelContent getNovelContent(context); chapterLines splitToChapters(novelContent); totalChapters chapterLines.length; currentChapter 1; insertChapter(editor, chapterLines[0]); updateStatusBar(); }); const nextChapterCommand vscode.commands.registerCommand(novel.nextChapter, () { if (currentChapter totalChapters) { clearInsertedContent(activeEditor); currentChapter; insertChapter(activeEditor, chapterLines[currentChapter - 1]); updateStatusBar(); } }); context.subscriptions.push(openReaderCommand, nextChapterCommand); }状态栏部分我创建了一个StatusBarItem显示“第X章/共Y章 小说阅读模式”并且点击状态栏可以快速唤出下一章命令const statusBar vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100); statusBar.command novel.nextChapter; statusBar.show(); function updateStatusBar() { statusBar.text $(book) 第${currentChapter}章 / 共${totalChapters}章; statusBar.tooltip 点击进入下一章; }整套交互闭环就算完成了用户打开阅读模式文件每一行行尾被追加小说注释标题和正文通过装饰器增强显示状态栏显示章节进度快捷键控制翻章。所有东西都停留在VSCode界面内部不需要切窗口。4. 打包发布从本地插件到VSCode Marketplace4.1 用vsce生成vsix安装包插件写好了功能测完了接下来就是让其他人能用上你的插件。这一步的核心工具是vsce它是VSCode官方提供的扩展打包发布命令行工具。先全局安装npm install -g vscode/vsce在插件项目根目录执行打包命令vsce package命令运行完当前目录下会出现一个.vsix文件这就是插件的安装包。在本地调试阶段你可以直接把vsix发给同事让他们在VSCode扩展面板里选择“从VSIX安装”很方便。但要注意vsce默认会把node_modules里的生产依赖打进去如果你的插件依赖了某些第三方npm包这些会被一并打包。对于我这个插件来说核心功能全部用的是VSCode自带API没有第三方依赖所以打包出来体积很小。如果你用了第三方库打包前最好用npm prune --production先清理无关依赖避免vsix包体积过大。另一个需要在打包前检查的点是LICENSE和README。vsce要求插件根目录至少要有README.md否则会提示缺少文件。如果准备公开到MarketplaceLICENSE文件建议也补上不然别人没办法合法地分发你的插件。4.2 创建Publisher并配置Personal Access Token要发布到VSCode Marketplace必须有一个发布者Publisher账号。这个账号是Azure DevOps体系里的概念和普通微软账号不一样得专门去Azure DevOps创建。步骤大概是打开Azure DevOps官网登录微软账号创建一个组织Organization名字随便起在组织设置里找到Personal Access TokensPAT生成一个有Marketplace发布权限的token用这个token在vsce里登录发布者这是VSCode插件发布流程里最容易劝退新手的一步因为界面层级比较深而且token权限配置一不留神就搞错。我踩过的坑是token的Organization必须选择创建的组织Scope必须包含Marketplace否则vsce会报出一个“publisher name not found”的错误而且提示信息很绕。登录命令很简单vsce login your-publisher-name它会提示你输入Personal Access Token。验证通过后你的本地环境就和Marketplace的发布者账号绑定上了。同样的publisher名称要写进package.json的publisher字段{ publisher: your-publisher-name, name: novel-reader-in-comments, displayName: Novel Reader - 代码注释阅读小说, version: 0.1.0 }4.3 发布、验证与版本迭代流程一切配置好后发布命令极其简单vsce publish这个命令会先跑一遍打包然后上传到Marketplace成功后输出一个发布链接。过几分钟后在VSCode扩展面板搜索你的插件名称就能找到可以直接安装。发布后可以在Marketplace管理后台看到下载量、安装量数据。如果发布了新版本只需要修改package.json里的version字段再次执行vsce publish即可。VSCode Marketplace对版本号有要求必须遵循语义化版本规范比如0.1.0、1.2.3不能直接用0.1这样的写法。每次重复发布同一版本号会报错更新插件务必记得先升版本号。验证发布成功的方法是在VSCode里打开扩展面板搜索插件名如果能看到你写的displayName和publisher名称就说明已经上线了。从发布到全量搜索可见会有几分钟的延迟不要急着反复重发。4.4 离线分发同事和朋友怎么装你的插件即使你发布了到Marketplace有些场景下依然需要离线分发比如公司内网机器不能联网或者有些同事用的VSCode版本跟不上最新API。离线安装只需要两步第一步在项目目录执行vsce package第二步把生成的.vsix文件发给对方对方在VSCode扩展面板点右上角的“...”菜单选择“从VSIX安装”然后重启编辑器即可。这里补充一个细节Marketplace对插件可支持的VSCode版本有要求如果插件里用到的API依赖比较高版本老版本VSCode用户即使手持vsix也无法安装会直接报“extension is not compatible”。所以在开发阶段就要确定一个你能接受的engines.vscode最低版本并在发布前用不同版本的VSCode实测一遍不能只看本机一个新版本就完事。5. 发布后收到反馈最多的8个问题问题排查实录5.1 插件装上了但又好像完全没反应这是反馈里最多的一类。插件装上后按F1输入命令名找不到“小说阅读打开阅读模式”这个命令。原因基本都出在package.json的activationEvents字段上。如果你用的是老版本VSCode或者package.json里没有显式写onCommand:novel.openReader这个激活事件命令就不会被注册。VSCode有个机制叫“懒加载”只有触发了你声明的激活事件插件代码才会真正执行。如果用户直接按命令面板执行命令VSCode会先检查插件是否注册了对应的激活事件没有的话直接找不到命令。解决办法在activationEvents里加入onCommand事件或者直接采用VSCode推荐的做法不写activationEvents而是用main字段和contributes中的配置自动生成“当有命令被执行时激活”的语义。简单说新版VSCode允许你省略activationEvents但前提是插件里所有命令都在contributes.commands里声明过。5.2 打开文件后小说内容不显示这个问题大概率出在装饰器没设置好或者行尾拼错位置。装饰器本质上是作用于某个Range的样式如果Range的end位置计算错了比如超出了当前行的长度VSCode可能不会渲染任何东西也可能渲染到不期望的位置。我当时遇到的一个具体情况是在带有很长代码行的文件上如果行尾追加的内容长度计算没有把Unicode字符占用的额外位置算进去Range会出现偏移导致整个装饰错位。因为VSCode的Position是基于UTF-16代码单元的中文、emoji这些字符每个占2个单元直接按JavaScript的字符串length计算没问题但如果你用了某些按字节计算的库就要小心。排查方式很简单在代码里给装饰器加上debug的日志输出打印每个Range的起止行列然后在调试控制台里人工核对是否和预期一致。5.3 文本里出现乱码或特殊字符小说文本和普通代码一样可能包含各种特殊字符比如中文引号、省略号、全角空格、反引号。这些字符在追加到行尾时本身没问题问题出在切换章节、清空内容阶段。如果你用正则来替换掉之前追加的注释遇到特殊字符很容易匹配不上导致上一次的残留文本和新章节内容重叠在一起。我的解决方案是不用正则去匹配删除而是记录每一次追加的Range在删除时直接用TextEdit.delete按精确范围删除function clearInsertedContent(editor: vscode.TextEditor | null) { if (!editor || !insertedRanges.length) return; const edit new vscode.WorkspaceEdit(); insertedRanges.forEach(range { edit.delete(editor.document.uri, range); }); vscode.workspace.applyEdit(edit); insertedRanges []; }用Range精确删除根本不用去关心文本内容是什么也不会误删用户原本写好的代码。5.4 打包后小说文本读不到了开发调试时间一切正常打包成vsix发给同事之后小说内容变成空白。这个问题前面提过一嘴根源几乎永远是vsce打包时漏掉了小说文本文件。因为vsce会读取.vscodeignore文件来决定发布时要排除哪些文件如果你在.vscodeignore里写了**/*.txt或者类似规则小说文件就没了。排查方式vsce ls这个命令会列出最终vsix包里的所有文件。如果发现resources/novel.txt不在列表里检查你的.vscodeignore是不是太宽松然后把它调整为只排除不需要的目录不要用宽泛的**/*.txt这种规则。5.5 大文件切换章节时编辑器卡顿当时有个使用场景是在一个几千行的日志文件里开阅读模式。每切换一章需要对当前文件所有行做一次Range计算和装饰器设置VSCode对一次setDecorations传入上千个Range会有明显卡顿。这是VSCode开发中很经典的性能问题装饰器数量和性能成反比。我的优化方案是控制装饰器的并发数量只对当前可见区域附近的行做装饰使用vscode.window.onDidChangeTextEditorVisibleRanges事件监听可视区域变化动态更新装饰器。这样即使文件有几千行一次渲染的Range数量也会被限制在几十个以内流畅度提升非常明显。另一个性能优化是小说文本按章节切分后不要一次性把所有章节的文字都渲染上去每次只处理当前章节需要覆盖的行数。对于没有代码内容的空行可以合并到一个Range里减少setDecorations的调用次数。5.6 其他几个高频反馈除了上面这几个大问题还有一些零散反馈退出阅读模式后代码文件偶尔会多出几个奇怪字符。这是因为清空时Range记录不全导致有一部分追加内容没被删除。解决办法是确保清空函数在任何异常路径中都会被调用最好用try/finally包裹关键逻辑。状态栏不显示。这多半是updateStatusBar没在activate里调用或者statusBar创建后忘了调用show()。在某种特殊语言文件里注释前缀不管用。比如在JavaScript的模板字符串内部即使行首有//某些场景下也会影响代码语义。为此我做了兜底如果检测到当前行处在字符串或注释内部就跳过这一行不追加。我个人在实际开发中的体会是VSCode插件开发真正的难点不在API本身而在于边界情况非常多。你面对的编辑器环境有几百种语言、几十种主题、不同的文件格式和用户操作习惯任何一个边界情况没处理到位就会变成某个用户的一句吐槽。所以插件发布出去只是开始后面根据反馈修问题、调性能、加功能才是做好一个插件真正花时间的部分。如果你也想动手做一个自己的VSCode插件我的建议是不要一上来就想着做特别宏大的功能从一个你真正需要的、小而具体的场景切入先发布一个能用的版本再慢慢迭代。代码注释看小说这个点子放在技术圈里算是个“歪点子”但它该走的VSCode插件开发流程、该踩的坑一个都没少。能把这个小东西完整走通你再去做其他正经工具的时候心里会特别有底。
返回列表