Typescript server is slow on Zed when compared to VSCode
Check for existing issues
- [X] Completed
Describe the bug / provide steps to reproduce it
The coding experience in a large Typescript monorepo (https://github.com/baptisteArno/typebot.io) is still an issue for me even though it now uses the vtsls, I still don't get the same speed as VSCode or even NeoVim (with vtsls lsp)
I'm just helpless, what is doing Zed that could cause this code error refresh so slow?
This also can be linked with:
- https://github.com/zed-industries/zed/issues/18621
Environment
Zed: v0.156.0 (Zed Preview) OS: macOS 15.0.0 Memory: 16 GiB Architecture: aarch64
If applicable, add mockups / screenshots to help explain present your vision of the feature
VSCode:
https://github.com/user-attachments/assets/82b329fc-e36d-4dca-ad89-9b8091198839
Zed:
https://github.com/user-attachments/assets/df83d644-848d-45e6-9da1-ce6ddf824030
If applicable, attach your Zed.log file to this issue.
No response
Could you also record a comparison with Neovim + VTSLS? VSC uses tsserver directly.
https://github.com/user-attachments/assets/265ac38b-45e9-41c8-90fd-4b8e4ed68321
LazyVim distro with that lsp config override:
return {
"neovim/nvim-lspconfig",
opts = function(_, opts)
opts.inlay_hints.enabled = false
opts.servers.vtsls.settings.typescript.tsserver = {
experimental = {
enableProjectDiagnostics = false,
},
}
opts.servers.vtsls.autoUseWorkspaceTsdk = true
return opts
end,
}
But as you can see in Zed, I'm hovering my mouse over the sessionState variable and it gives me the proper type so I guess that the LSP is up to date but Zed decides not to update the diagnostic overlay directly?
Same issue here, I'm running zed on fedora linux
Been facing the same issue for the past few months. The only workaround right now is to restart the LSPs once in a while.
I found this PR from vtsls. It seems Electron came with an unofficial Node version that came with pointer compression, which is also what VSCode is using. I played with it for a while. It does seem like the memory is relatively smaller, but I haven't really started coding with it.
https://github.com/user-attachments/assets/00178251-7b3d-4d2a-996c-e35023840996
[UPDATE] After trying to open files from at least 10 different sub-repos, I can see the tsserver memory usage cut nearly half, from 3GB~ down to 1GB~.
I'm not sure if this is good enough to reproduce the problem, but if you have a really large monorepo, try opening multiple files from multiple different sub-repos, and you will start noticing that the node memory usage will start to build up, which I think tsserver will likely get slow and unusable like the issue described.
Also happening for me
I wanted to give it another shot. New Zed install, dumb example but it's like this everywhere:
https://github.com/user-attachments/assets/f2c8aa00-a8b2-41ed-9e7b-73024fbb0c0b
Compared with Cursor (or VSCode):
https://github.com/user-attachments/assets/5b218320-9e26-4960-8e15-8b3a5a3bdf61
Guys... How is it not a priority? The reproduction is dead simple. Too bad Zed is so fast but the LSP refresh is total garbage??
@osiewicz, did you manage to reproduce? Clone this https://github.com/baptisteArno/typebot.io (or any non-toy typescript project)
Further discussion / debugging here: https://discord.com/channels/869392257814519848/873293828805771284/1343251336778743940
ok, i found what was wrong in my case, zed's default memory limit is different for vtsls and typescript-language-server you can test if it's works for your case by setting lsp settings to:
"lsp": {
"vtsls": {
"settings": {
"tsserver": {
"maxTsServerMemory": 8092
}
}
}
}
I'd offer that we set vtsls memory limit same as typescript-language-server https://github.com/zed-industries/zed/pull/25442
ok, i found what was wrong in my case, zed's default memory limit is different for vtsls and typescript-language-server you can test if it's works for your case by setting lsp settings to:
"lsp": { "vtsls": { "settings": { "tsserver": { "maxTsServerMemory": 8092 } } } }I'd offer that we set vtsls memory limit same as typescript-language-server #25442
Interesting, I always though that Zed default the vtsls max memory to 8092, but it doesn't seems to be the case according to your PR🤔 https://zed.dev/docs/languages/typescript#large-projects
[EDIT] Actually, I think the max memory is set correctly for vtsls, which is 8092 (https://github.com/zed-industries/zed/pull/17354/files). You probably got confuse by the Zed LSP settings hierarchy.
then
ok, i found what was wrong in my case, zed's default memory limit is different for vtsls and typescript-language-server you can test if it's works for your case by setting lsp settings to:
"lsp": { "vtsls": { "settings": { "tsserver": { "maxTsServerMemory": 8092 } } } }I'd offer that we set vtsls memory limit same as typescript-language-server #25442
Interesting, I always though that Zed default the vtsls max memory to 8092, but it doesn't seems to be the case according to your PR🤔 https://zed.dev/docs/languages/typescript#large-projects
[EDIT] Actually, I think the max memory is set correctly for vtsls, which is 8092 (https://github.com/zed-industries/zed/pull/17354/files). You probably got confuse by the Zed LSP settings hierarchy.
then i actually not sure what and where went wrong 😵💫, bc i tested locally and performance on my repo become great after i edited settings. And that worked in both cases: when it set as defaults in zed and when i edit settings
Based on my experience, I don't think memory is the problem here, where one of my monorepos(about 20+ sub-repos) always uses about 5GB at max, which it doesn't even hit the VTSL server max memory. And there is no problem with inspect types, go to definition, etc., not until I start changing some code, where the LSP will slowly fall apart.
Memory is not the issue. On nvim with vtsls with default memory limit (4Go), there is no issue.
Memory is not the issue. On nvim with vtsls with default memory limit (4Go), there is no issue.
maybe my issue was not related from the beginning 😅
I believe its related, on my case type changes takes much longer to take effect in other packages in a small monorepo compared to vscode. If the change is in something like generated code (prisma), it takes forever, restarting tsserver/zed works but it becomes a headache very fast.
It doesnt happen in vscode, which could be be because vscode's watchers are more aggressive? Its a wild guess but my system watcher limit gets maxed out only when vscode is running alongside my programs, not with zed.
maybe it's a good time to consider whether just looking into supporting typescript's upcoming go version? The VSCode extension already supports this
https://github.com/microsoft/typescript-go?tab=readme-ov-file#running-lsp-prototype
I experience the same issue in larger codebase. The autocompletion for component props or component lookup takes more than 5 seconds to show on CTRL+Space
maybe it's a good time to consider whether just looking into supporting typescript's upcoming go version? The VSCode extension already supports this
https://github.com/microsoft/typescript-go?tab=readme-ov-file#running-lsp-prototype
I guess, zed should should focus and improve the LSP stuff, instead of AI bubble, it's clear that zed still not compete with even the Neovim.
We now have an extension for tsgo: https://github.com/zed-extensions/tsgo#
I have a fairly large project (about a gigabyte of ts files) and until recently zed was doing great, even faster than vscode. However, the speed of ts degraded over time to the point where it eventually became slower to register for type changes than vscode, and later it became so slow that it became annoying.
Perhaps my problem is a bit different - first of all everything was fine initially, secondly increasing memory for vtsls, as well as switching to tsgo did not give any noticeable changes in speed
I use Zed on a quite large monorepo project. Unfortunately, I can also experience performance issues with TypeScript code navigation. The major pain point for me is the "Find All References" command. Sometimes it freezes for so long that I need to restart the editor. It works OK after the restart, but then as time goes by it starts to freeze again and again. The autocomplete snappiness doesn't feel great either.
I must admit that Zed is run on a rather outdated MacBook Pro in my case. It's not a vintage one though. And the main thing is that I don't experience these issues in VS Code (which is much more bloated than Zed in my opinion) on the same machine.
I use vtsls for TypeScript (and JavaScript). I also tried to adjust the memory dedicated to the TypeScript server (up to 10 GB), but it didn't help. The extra setting that I have configured for TypeScript is source.fixAll.eslint. Here's the part of my configuration related to JavaScript and TypeScript:
{
"languages": {
"JavaScript": {
"code_actions_on_format": {
"source.fixAll.eslint": true
},
"language_servers": ["vtsls"]
},
"TSX": {
"code_actions_on_format": {
"source.fixAll.eslint": true
}
},
"TypeScript": {
"code_actions_on_format": {
"source.fixAll.eslint": true
}
},
},
"lsp": {
"vtsls": {
"settings": {
"javascript": { "tsserver": { "maxTsServerMemory": 10240 } },
"typescript": { "tsserver": { "maxTsServerMemory": 10240 } }
}
}
}
}
It feels to me that the problem has something to do with the binding between the editor and the LSP.
I think the zed docs are wrong, or rather show settings that don't work.
when i switch from:
{
"lsp": {
"vtsls": {
"settings": {
// For TypeScript:
"typescript": { "tsserver": { "maxTsServerMemory": 16184 } },
// For JavaScript:
"javascript": { "tsserver": { "maxTsServerMemory": 16184 } }
}
}
}
}
to
{
"lsp": {
"vtsls": {
"settings": {
"tsserver": {
"maxTsServerMemory": 16184
}
}
}
}
it's a complete night and day difference. i haven't dug in, but have to assume that the above settings formulation doesn't actually stick.
I think the zed docs are wrong, or rather show settings that don't work.
when i switch from:
{ "lsp": { "vtsls": { "settings": { // For TypeScript: "typescript": { "tsserver": { "maxTsServerMemory": 16184 } }, // For JavaScript: "javascript": { "tsserver": { "maxTsServerMemory": 16184 } } } } } } to
{ "lsp": { "vtsls": { "settings": { "tsserver": { "maxTsServerMemory": 16184 } } } } it's a complete night and day difference. i haven't dug in, but have to assume that the above settings formulation doesn't actually stick.
whoever is reading this can ignore my previous comment, i think it was likely a fluke. when i look at the top output, i can see that max-old-space-size is correctly set to the value defined in settings, and that there are two tsserver processes (1 for js and ts each).
This vastly improved my speeds:
Update tsconfig's "include array" so that it is from the perspective of the root of the project, not the folder it is in.
Example:
"include": [
"frontend/**/*.ts",
"frontend/**/*.tsx",
"frontend/webpack.config.js",
"frontend/tailwind.config.js",
],
This vastly improved my speeds:
Update
tsconfig's"include array"so that it is from the perspective of the root of the project, not the folder it is in.Example:
"include": [ "frontend/**/*.ts", "frontend/**/*.tsx", "frontend/webpack.config.js", "frontend/tailwind.config.js", ],
Tried this for a couple of days. It does not help. Also my observation is that the LSP's message at the bottom of Zed is quick to print. I think the problem is that the popup, with actions/sugeestions, is waiting for something to complete making it feel slow.
Solution for TypeScript LSP Performance Issues in Zed
I was experiencing significant TypeScript lag in Zed on my macbook air when working with a large monorepo. The main issue was that when the AI agent modified code, tsserver couldn't keep up with the analysis, leading to memory leaks and slow LSP performance.
Solution: Using Bun runtime for typescript-language-server
This dramatically improved performance and significantly reduced RAM usage.
Step-by-step instructions:
-
Install Bun:
curl -fsSL https://bun.sh/install | bash -
Get Bun path:
which bun -
Install typescript-language-server globally via Bun:
bun add -g typescript-language-server -
Configure Zed (settings.json):
{ "languages": { "TSX": { "language_servers": ["typescript-language-server", "!vtsls"], "formatter": "prettier", "code_actions_on_format": { "source.addMissingImports.ts": true, "source.organizeImports": false, "source.fixAll.eslint": true } }, "TypeScript": { "language_servers": ["typescript-language-server", "!vtsls"], "formatter": "prettier", "code_actions_on_format": { "source.addMissingImports.ts": true, "source.removeUnusedImports": true, "source.organizeImports": false, "source.fixAll.eslint": true } } }, "lsp": { "typescript-language-server": { "binary": { "path": "/Users/<USER>/.bun/bin/bun", "arguments": [ "--bun", "/Users/<USER>/.bun/bin/typescript-language-server", "--stdio" ] } } } }
Caveats and workarounds:
- Downside: Auto-import doesn't appear in the context menu
- Workaround: Use
Ctrl + Spacefor autocomplete or set"source.addMissingImports.ts": truefor automatic imports on format
Now Zed performs much better in large monorepositories. I'm looking forward to the final typescript-go release, but this solution effectively addresses the performance issues in the meantime.
sorry to say but above solution still seems to be not work for me, feels like default vtsls perform faster then above solution for large project as well, so still zed both typescript LSPs are still slow and feels leggy. Neovim typescript LSPs still faster.
Solution: Using Bun runtime for typescript-language-server
This dramatically improved performance and significantly reduced RAM usage.
That one of the things that I tried awhile back, unfortunately using bun runtime actually generates more memory usage to me. Probably because of my codebase sizes.
So far the best result that gets is from using NodeJS instance from electron, but tedious to setup.
But there's nothing Zed can do other than waiting tsgo to be released.