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
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)
- 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
- Some are “off-the-shelf” provided by this esbuild
plugin
(uses jspm under the hood)
- Correctly inject custom Node.js shims into all dependencies
- Re-export certain packages such as TypeScript, PostCSS, svelte-preprocess (so we ensure they are fully processed and are bundled correctly for the browser)
- Modify the Svelte Language Server source to listen and synchronize it’s VFS with the separate TypeScript/JavaScript Language Server
- Change any
import('file:///path/to/file\.ext)
to read from the VFS, since importing a file won’t work - … 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)
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
The official Language Server is 1.69MB, so I’m personally not too bothered by the difference, all things considered!
- Centralize and allow consumers to pass in a conforming
fs
interface to thecreateServer
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