How to Configure Deno 2 LSPConfig on NeoVim 0.10.*

deno-2-lspconfig-neovim

Deno 2 has been released for a week now, and I find beauty in this new JavaScript engine, particularly in its new features. Its backward compatibility, which supports node_modules and package.json, stands out, as well as how intuitive its battery included command-line interface is and many more cool features. I’ve begun to develop a quite optimistic perspective on Deno 2 compared to other new modern JavaScript runtime environments like Bun. Once having a good ecosystem support I think it would take off and increase adoption by developer communities.

deno fmt can now format HTML, CSS, and YAML
deno lint now has Node specific rules and quick fixes
deno test now supports running tests written using node:test
deno task can now run package.json scripts
deno doc’s HTML output has improved design and better search
deno compile now supports code signing and icons on Windows
deno serve can run HTTP servers across multiple cores, in parallel
deno init can now scaffold libraries or servers
deno jupyter now supports outputting images, graphs, and HTML
deno bench supports critical sections for more precise measurements
deno coverage can now output reports in HTML

With native TypeScript support, Deno 2 makes development more developer-friendly by almost eliminating the need for TypeScript configuration—essentially a zero-config setup.

This morning, I wanted to build a small project with Deno 2, but I encountered an issue with the Language Server Protocol (LSP) in my NeoVim setup. It kept showing an error from the TypeScript server: “Cannot find name ‘Deno’”. After some investigation, I realized the issue was caused by the TSServer. In this case denols is the name of the parser represent Deno lang. Oh I am using LazyVim, it might different from other package installers like Plug. You can find some configuration doc from Deno website.

config = function()
	local lspconfig = require('lspconfig')
      -- Configure Deno's LSP (denols)
      lspconfig.denols.setup {
        on_attach = function(client, bufnr)
          on_attach(client, bufnr)
          -- Disable TypeScript server if it's causing issues
          if client.name == "tsserver" then
            client.stop()
          end
        end,
        root_dir = util.root_pattern("deno.json", "deno.jsonc"),
        init_options = {
          lint = true,
          unstable = true,
          suggest = {
            imports = {
              hosts = {
                ["https://deno.land"] = true,
                ["https://cdn.nest.land"] = true,
                ["https://crux.land"] = true
              }
            }
          }
        }
      }

      -- Configure tsserver but exclude it from Deno projects
      lspconfig.tsserver.setup {
        on_attach = function(client, bufnr)
          local root_dir = client.config.root_dir
          if root_dir and (util.path.exists(util.path.join(root_dir, "deno.json")) or
                util.path.exists(util.path.join(root_dir, "deno.jsonc"))) then
            client.stop() -- Disable tsserver in Deno projects
          else
            on_attach(client, bufnr)
          end
        end,
        root_dir = util.root_pattern("package.json", "tsconfig.json", "jsconfig.json"),
        -- Add any additional tsserver-specific settings here
      }
    end,

end,

I use Mason to manage the Lspserver, Linters and Formatters the code so I have to ensure that it support the Deno 2. There is a small change on the init.lua file.

Under dependencies > ensure_installed, I added a new parser “denols”. That’s it.

{
	-- LSP Configuration & Plugins
	'neovim/nvim-lspconfig',
    
	dependencies = {
		-- Automatically install LSPs to stdpath for neovim
		{
        	'williamboman/mason.nvim',
        	config = true,
        	opts = {
          	ensure_installed = {
            	"eslint_lsp",
            	"prettier",
            	"denols", -- configure to support Deno
            	"typescript-language-server"
     		},
    		automatic_installation = true,
    	}
      },
      'williamboman/mason-lspconfig.nvim',

      -- Useful status updates for LSP
      -- NOTE: `opts = {}` is the same as calling `require('fidget').setup({})`
      { 'j-hui/fidget.nvim', tag = 'legacy', opts = {} },

    },

It’s finally working! Get ready to taste it. I am planning to stick with Deno 2 for a while. Let’s see how far I can go with it. Although it’s relatively new and doesn’t have as much ecosystem support as Node.js. Oh wait, Deno use piggyback approach, it’s provide an option to use package from NPM 😀 Seem like there is no blockage on compatibility. I find it more developer-friendly with a lot of cool new features. Big thanks to Ryan Dahl for all your hard work. Alright, happy coding!