
nvim-lspconfig 中 Vue 语言配置vue_ls 与 vtsls 协同的完整指南【免费下载链接】nvim-lspconfigQuickstart configs for Nvim LSP项目地址: https://gitcode.com/GitHub_Trending/nv/nvim-lspconfig在 Neovim 里打开一个.vue文件模板里的样式提示正常script setup里的 TypeScript 却没有任何补全——这是 nvim-lspconfig 用户用 Vue 项目时最常见的半残状态。本文讲清两件事nvim-lspconfig 的vue_ls为什么必须和一个 TypeScript 服务器搭档工作以及从安装到排错的完整落地路径。你可以直接拿到可复制的配置、每个关键字段的作用说明和 4 个高频问题的自检方法。一个服务器管不了整个 .vue 文件Vue 单文件组件SFC里同时住着三类代码template的 HTML、style的 CSS、script的 TypeScript。早期方案volar 的 takeover 模式让一个服务器接管整份文件的所有请求简单但职责边界模糊。Vue 语言服务器 v3.0.0 起移除了 takeover 模式改为混合模式旧做法takeover 模式新做法混合模式v3.0.0 起架构单一服务器处理模板、样式、脚本全部请求vue_ls只管 CSS/HTML 部分TS 请求转发给 tsserverTypeScript 能力内嵌能力跟随语言服务器版本由vtsls或 Neovim 内置ts_ls提供独立升级配置成本一处配置两个服务器 一个 tsserver 插件多语言混用容易和独立 TS 服务器冲突天然与 JS/TS 生态共存理解这一点后后面的配置都是顺理成章的vue_ls遇到 TypeScript 请求时自己不会处理而是转发给 tsserver 通道。仓库里 lsp/vue_ls.lua 的文件头注释明确写着需要vtsls配合vue/typescript-plugin才能覆盖.vue文件里的 TypeScript。从安装到跑通三步完成配置第一步安装语言服务器用 npm 全局安装两个包Neovim 侧不需要额外依赖# vue_ls 的启动命令是 vue-language-servervtsls 的是 vtsls npm install -g vue/language-server vtsls/language-server第二步先给一个最小可运行版本最小配置只需 2 行先让它跑起来-- 两个服务器缺一不可vue_ls 管模板/样式vtsls 管 TS vim.lsp.enable(vue_ls) vim.lsp.enable(vtsls)此时打开.vue文件template的补全和script的基础 TS 能力应该都能用。如果script setup里项目类型、组合式 API 的提示还是残缺继续第三步。第三步完整版接入 vue/typescript-plugin让 tsserver 认识 Vue 单文件组件需要注册一个全局插件-- vue/typescript-plugin 的宿主包路径。 -- 用 mason.nvim 安装时Mason 默认把包装在 data 目录下 local vue_language_server_path vim.fn.stdpath(data) .. /mason/packages/vue-language-server/node_modules/vue/language-server local vue_plugin { name vue/typescript-plugin, -- tsserver 按这个名字加载插件 location vue_language_server_path, -- 必须是包的真实路径 languages { vue }, -- 关键即使 filetypes 里有 vue 也要写这里 configNamespace typescript, } vim.lsp.config(vtsls, { settings { vtsls { tsserver { globalPlugins { vue_plugin }, -- 插件在此注入 tsserver }, }, }, -- 默认只覆盖 js/ts 四种类型补上 vue 才能接管 SFC filetypes { typescript, javascript, javascriptreact, typescriptreact, vue }, }) vim.lsp.enable(vue_ls) vim.lsp.enable(vtsls)如果你没有用 mason而是npm install -g把vue_language_server_path改成vue/language-server在 npm 全局目录下的实际路径即可可用npm root -g查到前缀。拆开看内部on_init 的转发逻辑真正让这套配置自动工作的是 lsp/vue_ls.lua 里的on_init钩子。逐字段拆解cmd { vue-language-server, --stdio }启动命令。作用是用 stdio 模式拉起官方语言服务器一般不用改除非你用了自定义安装路径此时才需要补全可执行文件位置。filetypes { vue }、root_markers { package.json }前者决定哪个文件触发服务器后者决定它把项目根目录识别为哪里。monorepo 里根目录识别错了会导致它找不到正确的vue版本。on_init里的typescriptHandler核心逻辑。它监听tsserver/request通知然后依次查找当前缓冲区上的ts_ls、vtsls、typescript-tools三个候选客户端找到后调用typescript.tsserverRequest命令把请求转过去再把结果通过tsserver/response回传给vue_ls。这里有个值得注意的细节Neovim 0.11 内置的ts_ls排在第一位如果你环境里已有内置 TS 服务器vue_ls会优先转发给它。找不到任何 TS 客户端时的兜底重试 10 次每次间隔 100ms仍失败则弹出Could not find ts_ls, vtsls, or typescript-tools lsp client...错误。这条提示本身就是最重要的排查线索。对比 lsp/vtsls.lua 的root_dir函数它用package-lock.json、yarn.lock、pnpm-lock.yaml、bun.lockb等锁文件定位项目根并主动排除 Deno 项目检测到deno.json或更近的deno.lock就直接放弃。所以 vtsls 和 ts_ls 二选一即可不要同时启用两个。高频问题速查现象一script setup里补全残缺或报错根因vue/typescript-plugin没有注册到 tsserver典型是globalPlugins漏配、location路径错误或languages里少了vue。解法核对第三步配置。自检:checkhealth vtsls确认服务器健康再在.vue文件里跑:lua vim.lsp.get_clients({ bufnr 0, name vtsls })应返回一个客户端对象而非空表。现象二弹出 Could not find ts_ls, vtsls, or typescript-tools根因vue_ls已启动但缓冲区上没有任何 TypeScript 客户端。常见于只启用了vue_ls忘了vtsls或 vtsls 因根目录判定失败没有附着。解法确认vim.lsp.enable(vtsls)存在项目根要有package.json和至少一种锁文件vtsls 的root_dir靠它定位。自检命令同上另跑:checkhealth vtsls看 Server is active 状态。现象三服务器压根没启动根因npm 包没装或不在 PATH 里vue-language-server/vtsls可执行文件找不到。解法终端里跑which vue-language-server which vtsls在 Neovim 里等价检查print(vim.fn.exepath(vue-language-server)) -- 非空路径才算装上 print(vim.fn.exepath(vtsls))现象四Vue 2 项目行为异常根因vue_ls默认只支持 Vue 3 项目见 lsp/vue_ls.lua 文件头注释Vue 2 项目需要按官方 language-tools 文档做额外配置核心是让语言服务器找到项目内的 Vue 2 编译器依赖。解法先确认项目里装的是vue2.x:lua vim.fn.system(node -p require(\vue/package.json\).version)。版本对但行为异常时对照官方 README 的 Vue 2 章节补齐项目侧依赖而不是改 Neovim 配置。进阶性能与工程化以下两条针对多项目或大型仓库场景小项目可跳过。monorepo 零额外配置vtsls 本身支持 monorepo会为每个包自动找到对应的tsconfig.json/jsconfig.json无需为每个包起一个服务器实例。建议把统一版本的 TypeScript 放在 workspace 根让 vtsls 只解析一次 TS 二进制路径。按需加载可选只在打开 Vue 相关缓冲区时启用服务器减少纯 TS/JS 项目里无关进程的占用vim.api.nvim_create_autocmd(FileType, { pattern { vue, typescript, javascript, typescriptreact, javascriptreact }, callback function() if not vim.lsp.get_clients({ bufnr 0, name vtsls })[1] then vim.lsp.enable(vtsls) if vim.bo.filetype vue then vim.lsp.enable(vue_ls) end end end, })管理方式二选一mason.nvim 适合统一管理路径上文的stdpath(data)写法就是配合它npm 全局安装则更直接。两者混用时注意location指向要和实际安装位置一致否则插件静默失效。小结回顾主线Vue 3.0.0 起语言服务器不再包打天下vue_ls负责模板与样式TypeScript 能力通过on_init里的转发机制交给vtsls或内置ts_ls配置上的全部工作量就是装好两个包、注册vue/typescript-plugin、并保证languages里有vue。出问题先看:checkhealth vtsls和缓冲区客户端列表80% 的故障在这一步现形。延伸阅读doc/configs.md 中vue_ls与vtsls的完整条目以及 lsp/vue_ls.lua、lsp/vtsls.lua 的源码注释。如果你的项目里还有别的语言组合比如 Nuxt Solidity 这种混搭转发机制是怎么配合的欢迎在讨论区留言交流你的配置。【免费下载链接】nvim-lspconfigQuickstart configs for Nvim LSP项目地址: https://gitcode.com/GitHub_Trending/nv/nvim-lspconfig创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考