Skip to content

Instantly share code, notes, and snippets.

@snuffyDev
Last active October 15, 2023 20:22
Show Gist options
  • Save snuffyDev/75b8445a860db30a8bf30d6fa32c5364 to your computer and use it in GitHub Desktop.
Save snuffyDev/75b8445a860db30a8bf30d6fa32c5364 to your computer and use it in GitHub Desktop.

Svelte Language Server Write-Up

This is a write-up which goes over how I ported the Svelte Language Sever from the Node.js runtime, to being able to run within the web browser.

https://github.com/snuffyDev/svelte-language-server-web

The How

First thing’s first, a lot of credit goes to asafamr/svelte-vscode-web. I based my work off of his, while also improving the various techniques (as well as the functionality).

To answer the “how”, I’ll go over how I did the “port”/patch-job outside of what already was done (there’s a lot, although surprisingly not a lot for the actual language server itself)

  1. Ensure most of the Node.js shims used will enable dependencies to function, and for the language server to function properly.
    • Some are “off-the-shelf” provided by this esbuild plugin (uses jspm under the hood)
      • assert
      • buffer
      • stream
      • tty
      • net
      • process
    • Others are browserify-based packages
      • events
    • Others are custom made, as a full shim wasn’t needed, or the module needed to be deeply integrated with the “emulated Node” system
      • fs (fully integrates with the entirety of the language server + dependencies)
      • url
      • util
      • constants
      • module
  2. Correctly inject custom Node.js shims into all dependencies
  3. Re-export certain packages such as TypeScript, PostCSS, svelte-preprocess (so we ensure they are fully processed and are bundled correctly for the browser)
  4. Modify the Svelte Language Server source to listen and synchronize it’s VFS with the separate TypeScript/JavaScript Language Server
  5. Change any import('file:///path/to/file\.ext) to read from the VFS, since importing a file won’t work
  6. … and essentially wash, rinse, repeat until it worked.

Here can find the diff between the main branch of svelte-language-server-web compared to the language-server package in the official sveltejs/language-tools repository.

In the diff, it’s mostly just formatting changes, and the above mentioned minor changes. The web-vs-official-diff branch actually will build and the example/playground will run perfectly fine, albeit it is unable to read the Svelte config file in the VFS (due to the aforementioned importing file issue)

Is it any good on the web?

Honestly, it’s surprisingly good.

The bundle size isn’t too shabby either, considering it features a TS/JS language server + Svelte Language Server + svelte-preprocess + a lot of other nice things. (was going to put badges here, however bundlejs fails to generate a badge for both the official and web language server packages)

Minified + gzip’d svelte-language-server-web package is a total of 3.14MB

2151cbed1ad4e47d1a50ae883db37619.png

The official Language Server is 1.69MB, so I’m personally not too bothered by the difference, all things considered!

23c79a593d55915d6498898e6867af43.png

Potential improvements?

  • Centralize and allow consumers to pass in a conforming fs interface to the createServer function.
    • If it’s passed in, use that
    • If it’s not passed in, then attempt to use Node’s fs module
  • Migrate away from Node-specific dependencies
  • I know Volar.js was mentioned once or twice – it’s a major change in both thinking, and in how things work.
    • If that’s something that’s too massive of an undertaking, don’t migrate. If the current language server isn’t broken, then there’s not much to fix aside from DX and a little bit of UX
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment