Repository navigation
Multi-project graphql-config for the LSP: schema, documents, include, exclude, and fast startup #4616
Replies: 1 comment
|
Correction to the "Startup speed" section: dot directories are not skipped by the scan. The glob never matches files under them, but it still walks into them, and it follows symlinks while doing so. It turned up through git worktrees. Claude Code (and similar agent tools) create them inside the repo, at Measured with graphql-config 5.1.7
In the editor this showed up as the language server pinned at ~350% CPU and no autocomplete until the scan finished. Adding the worktree directory to const exclude = [
"**/node_modules/**",
"**/dist/**",
"**/generated/**",
"**/coverage/**",
".claude/worktrees/**",
];So exclude any directory inside the repo that holds whole checkouts or store symlinks (agent worktrees,
|
Uh oh!
There was an error while loading. Please reload this page.
I spent some time getting the GraphQL language server (vscode-graphql 0.13.x / graphql-language-service-server 2.15.0, graphql-config 5.1.6) to behave in a pnpm monorepo with three schemas. Sharing what I learned, because the interplay between
schema,documents,includeandexcludeis not obvious, and one setting turned a ~15 s startup into an almost instant one.The setup
Three projects, each with its own schema and its own document suffix (
*.api.gql,*.cms.gql,*.crm.gql). GraphQL also appears in.tsfiles that the LSP should ignore (they are handled by other tooling).What each key actually does
graphql-config decides which project a file belongs to with
GraphQLProjectConfig.match():and
GraphQLConfig.getProjectForFile()falls back to the first project that has neitherincludenorexcludewhen nothing matches.documents: the files the LSP pre-loads at startup. Fragment definitions are only indexed from here, so without it you getUnknown fragment "X"for fragments defined in other files.schema: also counts as "belongs to this project".include/exclude: only affect project membership; they never load anything.excludeis additionally used as the globignorelist when loadingdocuments.includeorexcludeon a project removes it from the fallback. That is the switch that stops the LSP from validating.tsfiles that are not part ofdocuments(see [lsp-server] 🐞 JS/TS files should only be checked when included indocumentsconfig glob #3588).The config that works
Notes:
schemamust be relative to the config file. An absolute path loads the schema fine, but never matches inmatch(), so the schema files end up in no project (File '.../api.schema.graphql' doesn't match any projectin the output). Withoutinclude/excludethe fallback hides this, and assigns all schema files to the first project.documentsandincludeboth.includealone breaks fragment lookup;documentsalone keeps the fallback and validates every.tsfile.there was an error loading the project config for this file ... doesn't match any project. It is harmless; the file is simply skipped (LSP Server: No Errors on mismatched file #2498).Startup speed: exclude
node_modulesThe LSP loads
documentsthrough graphql-tools, which does not ignorenode_modulesby default. A root-level glob like**/*.api.gqltherefore walks the whole pnpm store, once per project. Measured in our repo (warm FS cache, same 32/13/7 files found in every case):exclude**/node_modules/****/dist/**,**/generated/**,**/coverage/**Cold, the unexcluded case took ~15 s before
GraphQL Language Server caches initializedshowed up, and go-to-definition did nothing until then. With the exclude list startup is effectively instant.Dot-directories (
.next,.nx,.git) are already skipped, since the glob does not match dot paths by default. So the useful additions are build outputs (dist,build,coverage, generated code) that live in regular directories.Do not put the excludes in
documentsas!**/node_modules/**: negated globs indocumentsmakematch()returntruefor every file outsidenode_modules, which brings back the.tsvalidation. Useexclude.Related issues
documentsconfig glob #3588:.tsfiles validated through the fallback projectmatch()didClosehandler not boundnode_modules_cacheSchemaFiledrops the projectAll reactions