You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Neovim为每个缓冲区重复启动LSP客户端问题求助

解决Neovim LSP重复启动实例的问题

问题根源

你遇到的tsserver、tailwindcss等LSP重复启动的问题,核心原因是不同文件被识别为独立工作区(root_dir),Neovim会为每个独立工作区启动新的LSP客户端。

具体来看:

  • 你手动为tsserver指定了root_dir = require("lspconfig.util").find_git_ancestor,仅以Git仓库根目录作为工作区根路径
  • 其他LSP(如tailwindcss)使用默认检测逻辑,优先识别package.json、tailwind.config.js等配置文件所在目录
  • 当文件所在目录与Git根目录层级不同,或存在独立配置文件时,会被判定为不同工作区,触发新的LSP实例启动

修复方案

统一前端相关LSP的root_dir检测逻辑,确保同一项目下的所有文件被识别为同一个工作区:

步骤1:调整LSP配置结构

将需要统一root_dir的LSP从循环列表中移除,单独配置以覆盖默认逻辑:

-- Mappings.
-- See `:help vim.diagnostic.*` for documentation on any of the below functions
local opts = { noremap = true, silent = true }
vim.api.nvim_set_keymap("n", "<space>e", "<cmd>lua vim.diagnostic.open_float()<CR>", opts)
vim.api.nvim_set_keymap("n", "[d", "<cmd>lua vim.diagnostic.goto_prev()<CR>", opts)
vim.api.nvim_set_keymap("n", "]d", "<cmd>lua vim.diagnostic.goto_next()<CR>", opts)
vim.api.nvim_set_keymap("n", "<space>q", "<cmd>lua vim.diagnostic.setloclist()<CR>", opts)

-- Use an on_attach function to only map the following keys
-- after the language server attaches to the current buffer
local on_attach = function(client, bufnr)
    vim.api.nvim_buf_set_option(bufnr, "omnifunc", "v:lua.vim.lsp.omnifunc")

    -- Mappings.
    -- See `:help vim.lsp.*` for documentation on any of the below functions
    vim.api.nvim_buf_set_keymap(bufnr, "n", "gd", "<cmd>lua vim.lsp.buf.definition()<CR>", opts)
end

local capabilities = require("cmp_nvim_lsp").default_capabilities(vim.lsp.protocol.make_client_capabilities())
local rawCapabilitiesWithoutFormatting = vim.lsp.protocol.make_client_capabilities()
rawCapabilitiesWithoutFormatting.textDocument.formatting = false
rawCapabilitiesWithoutFormatting.textDocument.rangeFormatting = false
local capabilitiesWithoutFormatting = require("cmp_nvim_lsp").default_capabilities(rawCapabilitiesWithoutFormatting)

-- 保留无需特殊配置的LSP
local basic_servers = {
    "bashls",
    "clangd",
    "cssls",
    "eslint",
    "gopls",
    "html",
    "jsonls",
    "rust_analyzer",
    "svelte",
    "vimls",
    "volar",
    "prismals",
    "marksman",
}
for _, lsp in pairs(basic_servers) do
    require("lspconfig")[lsp].setup({
        on_attach = on_attach,
        flags = {
            debounce_text_changes = 300,
        },
        capabilities = capabilities,
    })
end

-- 统一配置前端相关LSP的root_dir
local shared_root_dir = require("lspconfig.util").find_git_ancestor

-- setup tsserver
require("lspconfig").tsserver.setup({
    on_attach = function(client, bufnr)
        client.server_capabilities.document_formatting = false
        client.server_capabilities.document_range_formatting = false

        on_attach(client, bufnr)
    end,
    flags = {
        debounce_text_changes = 300,
    },
    capabilities = capabilitiesWithoutFormatting,
    settings = {
        documentFormatting = false,
    },
    root_dir = shared_root_dir,
})

-- 单独配置tailwindcss,统一root_dir
require("lspconfig").tailwindcss.setup({
    on_attach = on_attach,
    flags = {
        debounce_text_changes = 300,
    },
    capabilities = capabilities,
    root_dir = shared_root_dir,
})

vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
    underline = true,
    -- This sets the spacing and the prefix, obviously.
    virtual_text = {
        spacing = 4,
    },
    signs = true,
    update_in_insert = true,
})

步骤2:验证修复效果

重启Neovim后打开多个项目文件,执行:LspInfo命令查看:

  • 同一项目下的文件应关联同一个LSP客户端实例
  • 不再出现重复启动的tsserver或tailwindcss进程

可选:自定义root_dir检测逻辑

如果你更倾向于以项目配置文件(如package.json)作为工作区根目录,可替换shared_root_dir为:

local shared_root_dir = require("lspconfig.util").root_pattern("package.json", "tsconfig.json", "tailwind.config.js")

该逻辑会优先识别包含上述配置文件的最近父目录作为工作区根,更符合前端项目常规结构。

额外注意事项

  • 避免对同一个LSP多次调用setup,否则可能导致配置冲突
  • 若为Monorepo项目,可根据需求调整root_dir逻辑,比如使用root_pattern("package.json")让每个子包作为独立工作区(此场景下多LSP实例属于正常情况)

内容的提问来源于stack exchange,提问作者Andrew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 11:16:01