You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(ts/js): improve monorepo support for Typescript, ESLint #3955
PROBLEM:
Monorepos (or "workspaces") in Typescript are more and more popular and
the associated tooling is evolving to improve the developer experience
in such setup. Especially, the `typescript-language-server` and the
`vscode-eslint-language-server` now supports monorepos, **removing the
need to spawn a different server for each package of a workspace**.
Example: with a few packages as the servers need to load every other
package to work (the `typescript-language-server`, even if spawned
multiple times with different `root_dir`, will load in memory other
packages to resolve the types), the amount of memory used grows
exponentially. But in fact, those servers support monorepos: they
support multiple configurations in subpackages and will load the correct
one to process a buffer. The ESLint server even supports loading
multiple ESLint binaries (and therefore versions), while keeping one
instance of the server.
SOLUTION:
Instead of only relying on the configuration files as `root_markers`,
discover the root of the package / monorepo by finding the Lock files
created by node package managers:
* `package-lock.json`: Npm
* `yarn.lock`: Yarn
* `pnpm-lock.yaml`: Pnpm
* `bun.lockb`: Bun
We still need to look at configuration files to enable the conditionnaly
attachment of the LSP for a buffer (for ESLint, we want to attach the
LSP only if there are ESLint configuration files) in case of LSP that
operates on files that are "generic" (like `typescript` or
`javascript`).
To do that, I replace the `root_markers` that were the configuration
files by a `root_dir` function that superseds them. It will both:
* look for a configuration file upward to check if the LSP needs to be attached
* look for the root of the "project" via the lock files to specify the `root_dir` of the LSP
PRIOR EXPERIMENTATIONS:
I've tried to play with the `reuse_client` quite a lot, trying to
understand if we need to spawn a new server or not looking at the
Typescript / ESLint binary that was loaded, but in fact it's way easier
to just have a better `root_dir` that is the true root of the project
for the LSP server: in case of those two servers, the root of the
package / monorepo.
I also tried to use the current directory opened as the `root_dir`, but
it's less powerful on nvim compared to VSCode as we navigate more inside
folders using terminal commands and then open vim.
I think this method also removes the need from a project-local config
(which could be quite useful anyway for ESLint flat config setting which
auto-detection is a bit unreliable / compute heavy) as this should work
normally accross all different setups.
Fixes#3910
Copy file name to clipboardExpand all lines: lsp/biome.lua
+32-8Lines changed: 32 additions & 8 deletions
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,10 @@
6
6
--- ```sh
7
7
--- npm install [-g] @biomejs/biome
8
8
--- ```
9
+
---
10
+
--- ### Monorepo support
11
+
---
12
+
--- `biome` supports monorepos by default. It will automatically find the `biome.json` corresponding to the package you are working on, as described in the [documentation](https://biomejs.dev/guides/big-projects/#monorepo). This works without the need of spawning multiple instances of `biome`, saving memory.
9
13
10
14
localutil=require'lspconfig.util'
11
15
@@ -34,13 +38,33 @@ return {
34
38
'vue',
35
39
},
36
40
workspace_required=true,
37
-
root_dir=function(_, on_dir)
38
-
-- To support monorepos, biome recommends starting the search for the root from cwd
Copy file name to clipboardExpand all lines: lsp/eslint.lua
+63-29Lines changed: 63 additions & 29 deletions
Original file line number
Diff line number
Diff line change
@@ -30,10 +30,33 @@
30
30
--- Messages handled in lspconfig: `eslint/openDoc`, `eslint/confirmESLintExecution`, `eslint/probeFailed`, `eslint/noLibrary`
31
31
---
32
32
--- Additional messages you can handle: `eslint/noConfig`
33
+
---
34
+
--- ### Monorepo support
35
+
---
36
+
--- `vscode-eslint-language-server` supports monorepos by default. It will automatically find the config file corresponding to the package you are working on. You can use different configs in different packages.
37
+
--- This works without the need of spawning multiple instances of `vscode-eslint-language-server`.
38
+
--- You can use a different version of ESLint in each package, but it is recommended to use the same version of ESLint in all packages. The location of the ESLint binary will be determined automatically.
39
+
---
40
+
--- /!\ When using flat config files, you need to use them across all your packages in your monorepo, as it's a global setting for the server.
Copy file name to clipboardExpand all lines: lsp/ts_ls.lua
+35-1Lines changed: 35 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -32,6 +32,14 @@
32
32
--- Use the `:LspTypescriptSourceAction` command to see "whole file" ("source") code-actions such as:
33
33
--- - organize imports
34
34
--- - remove unused code
35
+
---
36
+
--- ### Monorepo support
37
+
---
38
+
--- `ts_ls` supports monorepos by default. It will automatically find the `tsconfig.json` or `jsconfig.json` corresponding to the package you are working on.
39
+
--- This works without the need of spawning multiple instances of `ts_ls`, saving memory.
40
+
---
41
+
--- It is recommended to use the same version of TypeScript in all packages, and therefore have it available in your workspace root. The location of the TypeScript binary will be determined automatically, but only once.
Copy file name to clipboardExpand all lines: lsp/tsgo.lua
+35-1Lines changed: 35 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -5,6 +5,14 @@
5
5
--- `typescript-go` is experimental port of the TypeScript compiler (tsc) and language server (tsserver) to the Go programming language.
6
6
---
7
7
--- `tsgo` can be installed via npm `npm install @typescript/native-preview`.
8
+
---
9
+
--- ### Monorepo support
10
+
---
11
+
--- `tsgo` supports monorepos by default. It will automatically find the `tsconfig.json` or `jsconfig.json` corresponding to the package you are working on.
12
+
--- This works without the need of spawning multiple instances of `tsgo`, saving memory.
13
+
---
14
+
--- It is recommended to use the same version of TypeScript in all packages, and therefore have it available in your workspace root. The location of the TypeScript binary will be determined automatically, but only once.
Copy file name to clipboardExpand all lines: lsp/vtsls.lua
+34-1Lines changed: 34 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -57,6 +57,13 @@
57
57
--- ```
58
58
---
59
59
--- See `vue_ls` section and https://github.com/vuejs/language-tools/wiki/Neovim for more information.
60
+
---
61
+
--- ### Monorepo support
62
+
---
63
+
--- `vtsls` supports monorepos by default. It will automatically find the `tsconfig.json` or `jsconfig.json` corresponding to the package you are working on.
64
+
--- This works without the need of spawning multiple instances of `vtsls`, saving memory.
65
+
---
66
+
--- It is recommended to use the same version of TypeScript in all packages, and therefore have it available in your workspace root. The location of the TypeScript binary will be determined automatically, but only once.
0 commit comments