跳转到内容

code-server

2 篇包含标签 "code-server" 的文章

VSCode 与 code-server:浏览器端代码编辑方案选型

VSCode 与 code-server:浏览器端代码编辑方案选型

Section titled “VSCode 与 code-server:浏览器端代码编辑方案选型”

在构建浏览器端的代码编辑能力时,开发者面临一个关键选择:使用 VSCode 官方的 code serve-web 功能,还是采用社区驱动的 code-server 方案?这个选择不仅影响技术架构,还关系到许可证合规性和部署灵活性。

其实做技术选型这事儿,跟选择人生道路有点像。你选了一条路,就得一直走下去,想换路的时候,成本可就大了。

在 AI 辅助编程的时代,浏览器端的代码编辑能力变得越来越重要。用户期望在 AI 助手分析完代码后,能够立即在同一个浏览器会话中打开编辑器进行修改,无需切换应用。这种无缝的体验,怎么说呢,就像你想的时候,它就在那里——只是有时候它偏偏不在。

然而,在实现这个功能时,开发者面临一个关键的技术选型:是使用 VSCode 官方的 code serve-web 功能,还是采用社区驱动的 code-server 方案?

这两个方案各有优劣,选择错了可能会在后期带来不少麻烦。比如许可证问题——等到产品上线了才发现许可证不合规,那可就晚了。这跟谈恋爱有点像,一开始没想清楚,到头来才发现两个人的价值观根本不合,那付出的代价就大了。再比如部署方式——某个方案在开发环境跑得好好的,一上容器就各种问题,这种坑谁也不想踩,毕竟踩坑踩多了,人也就麻了。

本文分享的方案来自我们在 HagiCode 项目中的实践经验。HagiCode 是一个 AI 驱动的代码助手,在实现浏览器端代码编辑能力时,我们深入研究了这两个方案,最终在架构设计中同时支持两者,但默认优先选择 code-server。

项目地址:github.com/HagiCode-org/site

这是两个方案最根本的区别,也是我们在选型时最先考虑的因素。毕竟选型这事儿,第一步就要想清楚法律风险,不然以后出事了,怪谁呢?

code-server

  • MIT 许可证,完全开源
  • 由 Coder.com 公司维护,社区活跃
  • 可以自由商用、修改和分发
  • 无使用场景限制

VSCode code serve-web

  • 属于 Microsoft VSCode 产品的一部分
  • 使用 Microsoft 的许可证(VS Code 的许可证有商业使用限制)
  • 主要面向个人开发者使用
  • 企业级部署可能需要额外的商业授权考虑

从许可证角度看,code-server 对商业项目更友好。这一点在产品规划阶段就要想清楚,不然等到规模上来了再去迁移,那成本可就大了。毕竟迁移这事儿,说起来容易,做起来难,谁经历过谁知道。

许可证问题解决后,接下来就是部署方式。这直接影响到你的运维成本和架构设计,也间接影响着你每天的心情——部署越简单,心情越好,这道理大家都懂。

code-server

  • 独立的 Node.js 应用,可单独部署
  • 支持多种运行时来源:
    • 直接指定可执行文件路径
    • 系统 PATH 查找
    • NVM Node.js 22.x 环境自动检测
  • 服务器上无需安装 VSCode 桌面版
  • 容器化部署更简单

VSCode code serve-web

  • 必须依赖本地安装的 VSCode CLI
  • 需要本机有可用的 code 命令
  • 系统会过滤掉 VS Code Remote CLI 包装器
  • 主要设计用于本地开发场景

code-server 更适合服务器/容器部署场景。如果你的产品需要跑在 Docker 里,或者用户环境没有 VSCode,那选 code-server 就对了。毕竟简单就是美,复杂了容易出问题,出了问题还得修,修完了还可能引入新问题,这无穷无尽的循环,谁愿意经历呢?

两个方案在功能参数上也有一些差异,虽然不大,但在实际使用中可能会带来一些麻烦。这些细节就像生活中的小摩擦,不多,但多了就让人烦。

特性code-servercode serve-web
公开基路径/ (可配置)/vscode-server (固定)
认证方式--auth 参数,支持多种模式--connection-token / --without-connection-token
数据目录{DataDir}/code-server{DataDir}/vscode-serve-web
遥测默认禁用 --disable-telemetry依赖 VSCode 设置
更新检查可禁用 --disable-update-check依赖 VSCode 设置

这些差异在集成时需要特别注意。比如 URL 路径的不同,意味着前端代码需要做针对性处理。做开发的都知道,这种细节处理起来最费时间,但也没办法,不做就跑不通。

在实现编辑器切换功能时,可用性检测的逻辑也有所不同。这种差异就像人与人之间的相处方式,有的人喜欢直来直去,有的人喜欢含蓄委婉。

code-server

  • 始终作为可见实现返回
  • 即使不可用也会显示,提示 install-required 状态
  • 支持自动检测 NVM Node.js 22.x 环境

code serve-web

  • 只有检测到本机 code CLI 时才可见
  • 如果不可用,前端会自动隐藏此选项
  • 依赖本地 VSCode 安装状态

这种差异直接影响用户体验。code-server 的方式更透明,用户知道有这个选项,只是还没安装;code serve-web 的方式更隐蔽,用户可能都不知道还有这个选择。哪种方式更好?这得看产品定位了,毕竟用户体验这事儿,没有标准答案,只有合适不合适。

经过深入分析,HagiCode 项目采用了双实现架构,在架构层面同时支持两种方案。这倒不是我们技术选型困难症,而是真的有实际需求。毕竟在技术世界里,没有什么绝对正确的选择,只有最适合自己的选择。

// 默认活动实现是 code-server
// 如果保存了显式的 activeImplementation,优先尝试该实现
// 如果所请求实现不可用,解析器会尝试另一个实现
// 如果发生回退,返回 fallbackReason

我们默认选择 code-server,主要考虑是许可证和部署灵活性。但对于有本地 VSCode 环境的用户,code serve-web 也是一个不错的选择。毕竟给用户多一种选择,总归是好的,强迫别人接受单一方案,这事儿我干不出来。

CodeServerImplementationResolver 统一负责:

  • 启动预热时的实现选择
  • 状态读取时的实现选择
  • 项目打开时的实现选择
  • Vault 打开时的实现选择

这种设计让系统可以灵活应对不同场景,用户可以根据自己的环境选择最合适的实现。灵活设计这事儿,前期花的时间多一点,但后期省心,毕竟谁也不想到处改代码。

// localCodeAvailable=false 时,不显示 code serve-web
// localCodeAvailable=true 时,显示 code serve-web 配置

前端根据环境自动显示可用选项,避免用户看到无法使用的功能而困惑。用户困惑了,就来问你,问多了你也烦,烦多了就想改代码,改代码又可能引入 bug,这恶性循环,谁爱经历谁经历。

说了这么多理论,实际部署时要注意什么呢?其实理论说得再好,落地不行也没用,毕竟实践是检验真理的唯一标准。

对于容器化部署,code-server 是更优选择:

# 直接使用 code-server 官方镜像
FROM codercom/code-server:latest
# 或者通过 npm 安装
RUN npm install -g code-server

这样一层就搞定,不需要额外安装 VSCode。简单就是好,复杂了容易出错,这道理放哪儿都适用。

code-server 配置

{
"vscodeServer": {
"enabled": true,
"activeImplementation": "code-server",
"codeServer": {
"host": "0.0.0.0",
"port": 8080,
"executablePath": "",
"authMode": "none"
}
}
}

code serve-web 配置

{
"vscodeServer": {
"enabled": true,
"activeImplementation": "serve-web",
"serveWeb": {
"host": "0.0.0.0",
"port": 8080,
"executablePath": "/usr/local/bin/code"
}
}
}

配置这事儿,第一次麻烦点,配好了后面就省心了。就像生活一样,前期投入多一点,后面日子就好过一点。

code-server

http://localhost:8080/?folder=/path/to/project&vscode-lang=zh-CN

code serve-web

http://localhost:8080/vscode-server/?folder=/path/to/project&tkn=xxx&vscode-lang=zh-CN

注意路径和参数的差异,集成时需要分别处理。细节决定成败,这话一点都不假,少一个参数,可能就打不开页面。

系统支持运行时切换,切换时会自动停止旧实现:

// VsCodeServerManager 自动处理互斥
// 切换 activeImplementation 时,旧实现不会继续后台保活

这种设计让用户可以随时尝试不同实现,找到最适合自己的方案。毕竟适合自己的才是最好的,别人的建议仅供参考,最终还得自己试。

const { settings, runtime } = await getVsCodeServerSettings();
// runtime.activeImplementation: "code-server" | "serve-web"
// runtime.fallbackReason: 切换原因
// runtime.status: "running" | "starting" | "stopped" | "unhealthy"

状态可见,心里才有数。用户在遇到问题时可以快速定位是服务端问题还是自己操作问题。不知道状态的时候,人就容易慌,慌了就容易做出错误判断,这链条一旦启动,就停不下来了。

对比维度code-servercode serve-web推荐
许可证MIT(商用友好)Microsoft(有限制)code-server
部署灵活性独立部署依赖本地 VSCodecode-server
服务器适用性专为服务器设计主要面向本地开发code-server
容器化原生支持需要安装 VSCodecode-server
功能完整性接近桌面版官方完整版code serve-web
维护活跃度社区活跃Microsoft 官方各有优势

推荐策略:优先使用 code-server,在需要完整官方功能且具备本地 VSCode 环境时考虑 code serve-web。

本文分享的方案是 HagiCode 在实际开发中总结出来的。如果你觉得这套方案有价值,说明我们的工程实践还不错——那么 HagiCode 本身也值得关注一下。毕竟分享这事儿,有来有往才有趣,只有输出没有输入,总归不是长久之计。


如果本文对你有帮助:

感谢您的阅读,如果您觉得本文有用,欢迎点赞、收藏和分享支持。 本内容采用人工智能辅助协作,最终内容由作者审核并确认。

在浏览器中快速编辑代码:VSCode Web 集成实践

在浏览器中快速编辑代码:VSCode Web 集成实践

Section titled “在浏览器中快速编辑代码:VSCode Web 集成实践”

AI 分析完代码后,如何立即在浏览器中打开编辑器进行修改?本文分享 HagiCode 项目中集成 code-server 的实践经验,实现 AI 助手与代码编辑体验的无缝连接。

在 AI 辅助编程的时代,开发者经常需要快速查看和编辑代码。传统的开发流程是:在桌面端 IDE 中打开项目,定位文件,编辑,保存。只是这个流程在某些场景下,总觉得哪里不太对劲。

场景一:远程开发。当使用 HagiCode 这样的 AI 助手时,后端可能运行在远程服务器或容器中,本地无法直接访问项目文件。每次要查看或修改代码,都需要通过 SSH 或其他方式连接,体验割裂。这感觉就像你想见一个人,却隔着一层厚厚的玻璃,能看见却摸不着。

场景二:快速预览。AI 助手分析代码后,用户可能只是想快速浏览某个文件或做小幅修改。启动完整的桌面 IDE 显得重量级,浏览器内的轻量级编辑器更符合”快速查看”的需求。毕竟,谁愿意为了看一眼就大动干戈呢?

场景三:跨设备协作。在不同设备上工作时,浏览器中的编辑器提供了统一的访问入口,无需每台设备都配置开发环境。这倒也省事,毕竟人生苦短,何必重复劳动。

为了解决这些痛点,我们在 HagiCode 项目中集成了 VSCode Web。让 AI 助手与代码编辑体验无缝连接——AI 分析完代码后,用户可以立即在同一个浏览器会话中打开编辑器进行修改,无需切换应用。这种体验,怎么说呢,就像你想的时候,它就在那里。

本文分享的方案来自我们在 HagiCode 项目中的实践经验。HagiCode 是一个 AI 驱动的代码助手,旨在通过自然语言交互提升开发效率。在开发过程中,我们发现用户经常需要在 AI 分析和代码编辑之间快速切换,这促使我们探索如何将编辑器直接集成到浏览器中。

项目地址:github.com/HagiCode-org/site

技术选型:为什么是 code-server?

Section titled “技术选型:为什么是 code-server?”

在众多 VSCode Web 解决方案中,我们选择了 code-server。这个选择,其实也有几个考量:

功能完整。code-server 是 VSCode 的 Web 版本,支持桌面版的大部分功能,包括扩展系统、智能提示、调试等。这意味着用户在浏览器中也能获得接近桌面版的编辑体验。毕竟,谁又愿意在功能上妥协呢?

部署灵活。code-server 可以作为独立服务运行,也支持 Docker 容器化部署,与 HagiCode 的架构契合。我们的后端用 C# 编写,前端是 React,通过 REST API 与 code-server 服务通信。这就像搭积木,每块都有自己的位置。

认证安全。code-server 内置 connection-token 机制,防止未授权访问。每个会话都有唯一的 token,确保只有授权用户才能访问编辑器。安全感这东西,有了才知道重要。

HagiCode 的 VSCode Web 集成采用前后端分离的架构设计。

前端通过 vscodeServerService.ts 封装了与后端的交互:

// 打开项目
export async function openProjectInCodeServer(
id: string,
currentInterfaceLanguage?: string,
): Promise<VsCodeServerLaunchResponseDto>
// 打开 vault
export async function openVaultInCodeServer(
id: string,
path?: string,
currentInterfaceLanguage?: string,
): Promise<VsCodeServerLaunchResponseDto>

这两个方法的区别在于:openProjectInCodeServer 用于打开整个项目,而 openVaultInCodeServer 用于打开 Vault 的特定路径。对于 MonoSpecs 多仓库项目,系统会自动创建工作区文件。分工明确,各自做好自己的事,这就够了。

后端的 VaultAppService.cs 实现了核心逻辑:

public async Task<VsCodeServerLaunchResponseDto> OpenInCodeServerAsync(
string id,
string? relativePath = null,
string? currentInterfaceLanguage = null,
CancellationToken cancellationToken = default)
{
// 1. 获取设置并检查是否启用
var settings = await _vsCodeServerSettingsService.GetResolvedSettingsAsync(cancellationToken);
if (!settings.Enabled) {
throw new BusinessException(VsCodeServerErrorCodes.Disabled, "VSCode Server is disabled.");
}
// 2. 获取 vault 并解析启动目录
var vault = await RequireVaultAsync(id, cancellationToken);
var launchDirectory = ResolveLaunchDirectory(vault, relativePath);
// 3. 确保 code-server 运行并获取运行时信息
var runtime = await _vsCodeServerManager.EnsureStartedAsync(settings, cancellationToken);
// 4. 解析语言设置
var language = _vsCodeServerSettingsService.ResolveLaunchLanguage(
settings.Language,
currentInterfaceLanguage);
// 5. 构建启动 URL
return new VsCodeServerLaunchResponseDto {
LaunchUrl = AppendQueryString(runtime.BaseUrl, new Dictionary<string, string?> {
["folder"] = launchDirectory,
["tkn"] = runtime.ConnectionToken,
["vscode-lang"] = language,
}),
ConnectionToken = runtime.ConnectionToken,
OpenMode = "folder",
Runtime = VsCodeServerSettingsService.MapRuntime(
await _vsCodeServerManager.GetRuntimeSnapshotAsync(cancellationToken)),
};
}

这个方法的职责很清晰:检查设置、解析路径、启动服务、构建 URL。其中 ResolveLaunchDirectory 方法会进行路径安全检查,防止路径穿越攻击。代码就像诗,每一行都有自己的韵律。

后端通过 VsCodeServerManager 管理 code-server 进程:

  • 检查进程状态
  • 自动启动已停止的服务
  • 返回运行时快照(端口、进程 ID、启动时间等)

这种设计让系统可以自动处理 code-server 的生命周期,用户无需手动管理服务进程。毕竟,人生已经够复杂了,能自动化的就自动化吧。

HagiCode 支持多语言界面,code-server 也需要跟随这个设置。系统支持三种语言模式:

  • follow:跟随当前界面语言
  • zh-CN:固定中文
  • en-US:固定英文

通过 URL 参数 vscode-lang 传递给 code-server,确保编辑器语言与 HagiCode 界面保持一致。语言这东西,统一了才舒服。

对于 MonoSpecs 项目(包含多个子仓库的 mono-repo),系统会自动创建 .code-workspace 文件:

private async Task<string> CreateWorkspaceFileAsync(Project project, Guid projectId)
{
var folders = await ResolveWorkspaceFoldersAsync(project.Path);
var workspaceDocument = new {
folders = folders.Select(path => new { path }).ToArray(),
};
// 生成 workspace 文件...
}

这样可以在一个 code-server 实例中同时编辑多个子仓库,对于大型 mono-repo 项目非常实用。多个仓库在一个窗口里,就像多个故事在同一本书里。

HagiCode 前端使用 React + TypeScript,集成 code-server 的步骤倒也不复杂。

在项目卡片中添加 Code Server 按钮:

QuickActionsZone.tsx
<Button
size="sm"
variant="default"
onClick={() => onAction({ type: 'open-code-server' })}
>
<Globe className="h-3 w-3 mr-1" />
<span className="text-xs">{t('project.openCodeServer')}</span>
</Button>

这个按钮会触发打开动作,调用后端 API 获取启动 URL。一个按钮,承载一个动作,简单直接。

const handleAction = async (action: ProjectAction) => {
if (action.type === 'open-code-server') {
const response = await openProjectInCodeServer(project.id, i18n.language);
window.open(response.launchUrl, '_blank', 'noopener,noreferrer');
}
};

使用 window.open 在新标签页中打开 code-server,noopener,noreferrer 参数确保安全性。安全这东西,再怎么小心都不为过。

在 Vault 列表中添加类似的编辑按钮:

const handleEditVault = async (vault: VaultItemDto) => {
const response = await openVaultInCodeServer(vault.id);
window.open(response.launchUrl, '_blank', 'noopener,noreferrer');
};

项目和 Vault 使用相同的打开方式,保持了交互的一致性。一致性的重要,不亚于功能本身。

code-server 的 URL 格式,其实也有点讲究:

文件夹模式

http://{host}:{port}/?folder={path}&tkn={token}&vscode-lang={lang}

工作区模式

http://{host}:{port}/?workspace={workspacePath}&tkn={token}&vscode-lang={lang}

其中 tkn 是连接 token,每次启动 code-server 时自动生成,确保访问安全。vscode-lang 参数控制编辑器界面语言。这些参数各有各的用处,缺一不可。

用户与 HagiCode 对话,AI 分析项目代码并发现潜在问题。用户点击 “Open in Code Server” 按钮直接在浏览器中打开编辑器,查看问题文件并修复,然后返回 HagiCode 继续对话。整个流程在浏览器中完成,无需切换应用。这种感觉,怎么说呢,就像流水一样顺畅。

用户创建了学习某个开源项目的 Vault,想在 docs/ 目录添加学习笔记。通过 code-server 直接在浏览器中编辑 Markdown 文件,保存后 HagiCode 可以同步读取更新的笔记内容。这对于构建个人知识库非常有用。知识这东西,越积累越有价值。

MonoSpecs 项目包含多个子仓库,code-server 自动创建多文件夹工作区。用户在浏览器中可以同时编辑多个仓库的代码,修改后提交到各自的 Git 仓库。这种工作方式特别适合需要跨仓库修改的场景。多个仓库一起改,就像同时处理多件事情,需要点技巧。

在实现 code-server 集成时,安全性是需要重点关注的问题。毕竟,安全这种事,出了问题就晚了。

connection-token 是随机生成的,不应泄露。建议在 HTTPS 环境下使用,防止 token 被中间人截获。敏感信息,还是保护好为妙。

后端实现了路径穿越检查:

private static string ResolveLaunchDirectory(VaultRegistryEntry vault, string? relativePath)
{
var vaultRoot = EnsureTrailingSeparator(Path.GetFullPath(vault.PhysicalPath));
var combinedPath = Path.GetFullPath(Path.Combine(vaultRoot, relativePath ?? "."));
if (!combinedPath.StartsWith(vaultRoot, StringComparison.OrdinalIgnoreCase))
{
throw new BusinessException(VaultRelativePathTraversalCode, "Relative path traversal detected.");
}
return combinedPath;
}

这段代码确保用户无法通过 ../ 等方式访问 vault 目录之外的文件。边界检查这种事,做总比不做强。

code-server 进程以适当的用户权限运行,避免访问系统敏感文件。建议使用专用用户运行 code-server 服务。权限控制,该有的还是要有。

code-server 会消耗服务器资源,以下是一些优化建议:

  • 监控 CPU/内存使用,必要时调整资源限制
  • 大型项目可能需要增加超时时间
  • 实现会话超时自动清理,释放资源
  • 考虑使用缓存减少重复计算

HagiCode 提供了运行时状态监控 API,前端可以通过 getVsCodeServerSettings() 获取当前状态:

const { settings, runtime } = await getVsCodeServerSettings();
// runtime.status: 'disabled' | 'stopped' | 'starting' | 'running' | 'unhealthy'
// runtime.baseUrl: "http://localhost:8080"
// runtime.processId: 12345

这个设计让用户可以清楚了解 code-server 的健康状态,在出现问题时快速定位。状态可见,心里才有数。

在实现过程中,我们发现了一些影响用户体验的细节,值得特别关注:

首次打开 code-server 可能需要等待启动,这个时间可能从几秒到半分钟不等。建议在前端显示加载状态,让用户知道系统正在处理。等待这事儿,有反馈就好。

浏览器可能会阻止弹窗,需要提示用户手动允许。HagiCode 在首次打开时会显示引导信息,告诉用户如何设置浏览器权限。用户体验,就是在这些细节里体现的。

建议显示运行时状态(启动中/运行中/错误),这样用户在遇到问题时可以知道是服务端问题还是自己操作问题。知道问题出在哪里,至少心里有底。

code-server 的配置倒也不复杂:

{
"vscodeServer": {
"enabled": true,
"host": "0.0.0.0",
"port": 8080,
"language": "follow"
}
}

enabled 控制功能开关,hostport 指定监听地址,language 设置语言模式。这些配置可以通过 UI 界面修改,实时生效。简单的东西,往往最好用。

HagiCode 的 VSCode Web 集成提供了一个优雅的解决方案:让 AI 助手与代码编辑体验无缝连接。通过在浏览器中集成 code-server,用户可以快速响应 AI 的分析结果,在同一个浏览器会话中完成从分析到编辑的完整流程。

这套方案的几个关键优势:一是统一体验,项目和 Vault 使用相同的打开方式;二是多仓库支持,MonoSpecs 项目自动创建工作区;三是安全可控,运行时状态监控和路径安全检查。

本文分享的方案是 HagiCode 在实际开发中总结出来的。如果你觉得这套方案有价值,说明我们的工程实践还不错——那么 HagiCode 本身也值得关注一下。毕竟,好东西值得被更多人看见。

  • HagiCode GitHub:github.com/HagiCode-org/site
  • HagiCode 官网:hagicode.com
  • code-server 官网:coder.com/code-server
  • 相关代码文件:
    • repos/web/src/services/vscodeServerService.ts
    • repos/hagicode-core/src/PCode.Application/Services/VaultAppService.cs
    • repos/hagicode-core/src/PCode.Application/ProjectAppService.VsCodeServer.cs

如果本文对你有帮助:

感谢您的阅读,如果您觉得本文有用,欢迎点赞、收藏和分享支持。 本内容采用人工智能辅助协作,最终内容由作者审核并确认。