Configure volar 2.0 (with typescript support)
Last updated: 2024-10-26
Volar 2.0 has discontinued their "take over mode" which in previous version provided support for typescript in vue files. The new approach to get typescript support involves using the typescript language server along side volar. So here I'll show you the steps necessary to make the typescript language server (ts_ls
) work in vue files.
Is worth mention the solution I'm about to show is not specific to lsp-zero. You can follow these steps even if you don't use lsp-zero.
"The trick"
At the heart of everything what you need to do is install the package @vue/typescript-plugin using npm
and then configure the typescript language server to use it.
For mason.nvim
there's a note at the end of the post. I recommend reading the whole post then do the steps.
NPM packages and where to install them...
We are going to install some packages using npm install -g
.
But before you do anything, I recommend creating an .npmrc
file in your home directory. So you can control where npm
will install the packages. Something like this.
prefix=/home/dev/.local/share/npm
global-bin-dir=/home/dev/.local/share/npm/bin
# note: these are example paths. replace them with a valid paths
Use the prefix
and global-bin-dir
options to tell npm
where it should install the global packages. If you do this you don't have to worry about node version managers changing your paths.
After you have an .npmrc
in your home directory with all the right options make sure global-bin-dir
is included in your PATH
environment variable.
NPM install
Now you can install the language server for typescript. Execute this command in your terminal.
npm install -g typescript typescript-language-server
And you install volar
using this command.
npm install -g @vue/language-server
Since @vue/typescript-plugin
is a dependency of @vue/language-server
we don't have to specify it in the npm install command.
After you install these language servers is a good idea to check if Neovim "knows" where they are. For example, you can open Neovim and execute this command.
echo exepath('vue-language-server')
This should show you the path to the executable of vue-language-server
. If it doesn't it means you need to setup your PATH
environment variable properly. Make sure it contains the path where npm
install the executables of global packages.
The typescript language server
Now it's time to go to our Neovim configuration.
So the way you I usually setup ts_ls
is by calling the setup function of lspconfig. Like this.
require('lspconfig').ts_ls.setup({})
There is where we need to add our new settings. We will add a lua table called init_options
and inside that we add a plugins table.
require('lspconfig').ts_ls.setup({
init_options = {
plugins = {
}
},
})
Inside this plugins
table we need to add the path where @vue/typescript-plugin
is located. And here is where it gets tricky. The path would be something like this:
local vue_typescript_plugin = '/home/dev/.local/share/npm'
.. '/lib/node_modules'
.. '/@vue/language-server/node_modules'
.. '/@vue/typescript-plugin'
But this first part /home/dev/.local/share/npm
, you should replace it with the location of the "npm prefix" in your system. To get that information you can execute this command in your terminal.
npm config get prefix
After you figure out where is @vue/typescript-plugin
you can add it to the plugins table of ts_ls
.
local vue_typescript_plugin = '/home/dev/.local/share/npm'
.. '/lib/node_modules'
.. '/@vue/language-server/node_modules'
.. '@vue/typescript-plugin'
require('lspconfig').ts_ls.setup({
init_options = {
plugins = {
{
name = "@vue/typescript-plugin",
location = vue_typescript_plugin,
languages = {'javascript', 'typescript', 'vue'}
},
}
},
})
And the last detail we need to take care of is adding vue
as a filetype supported by ts_ls
.
local vue_typescript_plugin = '/home/dev/.local/share/npm'
.. '/lib/node_modules'
.. '/@vue/language-server/node_modules'
.. '@vue/typescript-plugin'
require('lspconfig').ts_ls.setup({
init_options = {
plugins = {
{
name = "@vue/typescript-plugin",
location = vue_typescript_plugin,
languages = {'javascript', 'typescript', 'vue'}
},
}
},
filetypes = {
'javascript',
'javascriptreact',
'javascript.jsx',
'typescript',
'typescriptreact',
'typescript.tsx',
'vue',
},
})
Don't forget about volar
After you are done with ts_ls
you can just call the setup function for volar.
require('lspconfig').volar.setup({})
Note for mason.nvim users
You don't have to execute npm install -g
, you can install volar
with mason.nvim
and then get the path to @vue/typescript-plugin
with some utility functions.
You can define the variable vue_typescript_plugin
like this.
local vue_typescript_plugin = require('mason-registry')
.get_package('vue-language-server')
:get_install_path()
.. '/node_modules/@vue/language-server'
.. '/node_modules/@vue/typescript-plugin'
So the complete configuration code should be something like this.
require('mason').setup({})
require('mason-lspconfig').setup({
ensure_installed = {
'ts_ls',
'volar',
},
handlers = {
function(server_name)
require('lspconfig')[server_name].setup({})
end,
volar = function()
require('lspconfig').volar.setup({})
end,
ts_ls = function()
local vue_typescript_plugin = require('mason-registry')
.get_package('vue-language-server')
:get_install_path()
.. '/node_modules/@vue/language-server'
.. '/node_modules/@vue/typescript-plugin'
require('lspconfig').ts_ls.setup({
init_options = {
plugins = {
{
name = "@vue/typescript-plugin",
location = vue_typescript_plugin,
languages = {'javascript', 'typescript', 'vue'}
},
}
},
filetypes = {
'javascript',
'javascriptreact',
'javascript.jsx',
'typescript',
'typescriptreact',
'typescript.tsx',
'vue',
},
})
end,
},
})