## 概要 [[Vue Language Tools]]のv3がリリースされたとのことで、[[Neovim]]環境をv2からv3に移行してみた。 <div class="link-card-v2"> <div class="link-card-v2-site"> <img class="link-card-v2-site-icon" src="https://github.githubassets.com/favicons/favicon.svg" /> <span class="link-card-v2-site-name">GitHub</span> </div> <div class="link-card-v2-title"> Neovim </div> <div class="link-card-v2-content"> ⚡ High-performance Vue language tooling based-on Volar.js - vuejs/language-tools </div> <img class="link-card-v2-image" src="https://opengraph.githubassets.com/226ec5d235c0c068e8f5b0364cf875f79a4351764be8b885310af140c8fe3c19/vuejs/language-tools" /> <a href="https://github.com/vuejs/language-tools/wiki/Neovim"></a> </div> 上記は[[mason.nvim]]がメインストリームの案内だが、本ノートは[[mise]]がメインストリームとなっている。 ## 環境 | 対象 | バージョン | | ------------------ | ---------- | | [[macOS]] | 15.5 | | [[Neovim]] | 0.11.2 | | [[nvim-lspconfig]] | d8f03bf | | [[mise]] | 2025.7.1 | | 対象 | 対応前バージョン | 対応後バージョン | | ------------------------------------------------------- | -------- | -------- | | [[TypeScript Language Server]] (ts_ls) | 4.3.4 | ❌ | | [[vtsls]] | ❌ | 0.2.9 | | [[@vue language-server\|@vue/language-server]] (vue_ls) | 2.2.10 | 3.0.1 | | [[@vue typescript-plugin\|@vue/typescript-plugin]] | 2.2.10 | ❌ | ## 変更点 - [[TypeScript Language Server]] (ts_ls) の代わりに [[vtsls]] を使う - [[@vue typescript-plugin|@vue/typescript-plugin]] の明示的な依存は削除し、代わりに[[@vue language-server|@vue/language-server]]の暗黙的な依存を使用する ## 変更後の関連イメージ ![[20250708_08_39_41.webp]] ![[TypeScript-Vue-LSP-Neovim.canvas|TypeScript-Vue-LSP-Neovim]] > [!attention] > あってるかは自信ない。 ## 変更前の設定 ### 前提 各LSP設定ファイルのパスは `nvim/after/lsp` 配下である。パスの由来は以下を参照。 <div class="link-card-v2"> <div class="link-card-v2-site"> <img class="link-card-v2-site-icon" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/favicon-64.png" /> <span class="link-card-v2-site-name">Minerva</span> </div> <div class="link-card-v2-title"> 📝nvim-lspconfigでruntimepath配下のluaディレクトリ配下に配置したLSP設定が読み込まれない </div> <div class="link-card-v2-content">Neovim 0.11環境でnvim-lspconfigのLSP設定がruntimepath配下のlua/lspディレクトリから読み込まれず、root_markersが上書きされる問題の原因はruntimepathの順序である。解決策は~/.config/nvim/after/luaへ移動することである。</div> <img class="link-card-v2-image" src="https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/troubleshooting.webp" /> <a data-href="📝nvim-lspconfigでruntimepath配下のluaディレクトリ配下に配置したLSP設定が読み込まれない" class="internal-link"></a> </div> %%[[📝nvim-lspconfigでruntimepath配下のluaディレクトリ配下に配置したLSP設定が読み込まれない]]%% ### `ts_ls.lua` ```lua return { workspace_required = true, root_markers = { "tsconfig.json", "jsconfig.json" }, init_options = { plugins = { { name = "@vue/typescript-plugin", location = os.getenv("HOME") .. "/.local/share/mise/installs/npm-vue-typescript-plugin/latest/lib/node_modules/@vue/typescript-plugin ", languages = { "javascript", "typescript", "vue" }, }, }, }, filetypes = { "javascript", "typescript", "vue", }, } ``` ### `vue_ls.lua` ```lua return {} ``` ## インストール/アンインストール ### [[vtsls]]のインストール ```console mise use -g npm:@vtsls/language-server ``` ### [[TypeScript Language Server]]のアンインストール [[VSCode]]のビルトイン拡張である[[TypeScript and JavaScript Language Features]]を[[LSP]]としてラップしている[[vtsls]]があるので不要。[[TypeScript]]はバッチリ。 ```console mise rm npm:typescript-language-server ``` ### [[@vue typescript-plugin|@vue/typescript-plugin]]のアンインストール [[@vue language-server|@vue/language-server]]の依存関係に[[@vue typescript-plugin|@vue/typescript-plugin]]が含まれており、そちらを使ったほうがバージョン差異も出ない。そのため不要。 ```console mise rm npm:@vue/typescript-plugin ``` ### [[@vue language-server|@vue/language-server]]のアップデート ```console mise up npm:@vue/language-server ``` ## 変更後の設定 `ts_ls.lua` は削除する。 > [!add] #2025/08/07 追記 > [vue_lsがts_lsにも対応したらしい](https://github.com/neovim/nvim-lspconfig/pull/3986) ### `vtsls.lua` ```lua local vue_language_server_path = os.getenv("HOME") .. "/.local/share/mise/installs/npm-vue-language-server/latest/lib/node_modules/@vue/language-server" local vue_plugin = { name = "@vue/typescript-plugin", location = vue_language_server_path, languages = { "vue" }, configNamespace = "typescript", } return { -- root_markersはデフォルトだと .git も含まれており、Denoプロジェクトでも有効になってしまうのを避けるため設定し直している root_markers = { "package.json", "tsconfig.json", "jsconfig.json" }, workspace_required = true, settings = { vtsls = { tsserver = { globalPlugins = { vue_plugin, }, }, }, }, filetypes = { "typescript", "javascript", "javascriptreact", "typescriptreact", "vue" }, } ``` ### `vue_ls.lua` > [!add] #2025/07/15 追記 > [85379d0](https://github.com/neovim/nvim-lspconfig/commit/85379d0) のコミットで[[nvim-lspconfig]]の[[@vue language-server|vue_ls]]対応がされたため、`vue_ls.lua` の中身は `return {}` で動くようになった。よって以下のコードは不要。 ```lua return { on_init = function(client) client.handlers["tsserver/request"] = function(_, result, context) local clients = vim.lsp.get_clients({ bufnr = context.bufnr, name = "vtsls" }) if #clients == 0 then vim.notify("Could not found `vtsls` lsp client, vue_lsp would not work without it.", vim.log.levels.ERROR) return end local ts_client = clients[1] local param = unpack(result) local id, command, payload = unpack(param) ts_client:exec_cmd({ title = "vue_request_forward", -- You can give title anything as it's used to represent a command in the UI, `:h Client:exec_cmd` command = "typescript.tsserverRequest", arguments = { command, payload, }, }, { bufnr = context.bufnr }, function(_, r) local response_data = { { id, r.body } } client:notify("tsserver/response", response_data) end) end end, } ``` ### 他 `vim.lsp.enable({...})` で `vtsls` と `vue_ls` の指定が必要。 ## トラブルシューティング ### executing vim.schedule lua callbackエラー ```error  Error 15:10:45 msg_show.lua_error Error executing vim.schedule lua callback: /Users/tadashi-aikawa/.config/nvim/after/lsp/vue_ls.lua:21: attempt to index local 'r' (a nil value) stack traceback: /Users/tadashi-aikawa/.config/nvim/after/lsp/vue_ls.lua:21: in function 'handler' ...im-macos-arm64/share/nvim/runtime/lua/vim/lsp/client.lua:681: in function '' vim/_editor.lua: in function <vim/_editor.lua:0> ``` エラーメッセージでは分かりにくいが `vue_language_server_path` が間違っているとこのエラーになる。特に以下2点を確認する。 - `~/...` ではなく `os.getenv("HOME") .. "/..."` でホームディレクトリを指定しているか? - パスは[[@vue language-server|@vue/language-server]]のrootを指しているか? 正しいパスだとこんな感じになる。最初は[[Language Server]]の実行ファイルを指定してハマった...。 ```console $ ll ~/.local/share/mise/installs/npm-vue-language-server/latest/lib/node_modules/@vue/language-server drwxr-xr-x@ - 5 Jul 19:35  bin .rw-r--r--@ 11 5 Jul 19:35  index.d.ts .rw-r--r--@ 14k 5 Jul 19:35  index.js drwxr-xr-x@ - 5 Jul 19:35  lib .rw-r--r--@ 1.1k 5 Jul 19:35  LICENSE .rw-r--r--@ 12 5 Jul 19:35  node.d.ts .rw-r--r--@ 6.5k 5 Jul 19:35  node.js drwxr-xr-x@ - 5 Jul 19:35  node_modules .rw-r--r--@ 742 5 Jul 19:35  package.json .rw-r--r--@ 49 5 Jul 19:35  protocol.d.ts .rw-r--r--@ 860 5 Jul 19:35  protocol.js ``` ## 参考 - [Versions 3 Upgrade guide for none-vscode editors. · vuejs/language-tools · Discussion #5456](https://github.com/vuejs/language-tools/discussions/5456)