I am Johnson, the author of Volar (now known as Vue Language Tools), and we released version 2.0 in March this year. This article will introduce you to the improvements and development experiences brought by 2.0.
In Vetur and Volar v1, we implemented Vue's IDE support through the Language Server Protocol (LSP), which works well for most small to medium-sized Vue projects, but there may be problems for very large projects.
The memory usage of the TS Server and Vue language server is proportional to the number of project files and lines of code (including .d.ts
files in node_modules), with each file generating expensive TS AST instances. In extreme cases (for example, when some dependencies contain thousands of .d.ts
files), memory usage can spike, and when the TS Server and Vue Language Server each need a copy of the project files' TS AST, it could exhaust the computer's memory.
In the above figure, the Vue Language Server occupies additional memory compared to the TS Server, which is occupied by Vue files. This part of the memory size is affected by the number of Vue files and the number and size of .d.ts
files in node_modules that are directly or indirectly referenced by Vue files.
To allow .ts files to recognize .vue component types, as well as support renaming variables in .vue from .ts, etc., we also need to install the TypeScript Vue Plugin, ultimately leading to double the memory usage.
To address this issue, in Volar v1, we introduced a takeover mode, where when you manually disable the TS Server, the Vue Language Server takes over IDE support for .ts files. Finally, the memory issue seemed to be resolved.
If you have ever enabled takeover mode, you might find it not so convenient to use. You need to:
- Find the list of Built-in extensions in VSCode
- Locate "TypeScript and JavaScript Language Features"
- Disable it for each of your Vue project workspaces
If you don't look at Vue's documentation, you might not even know about the existence of takeover mode, hence this feature has always been used by only a minority of users.
Moreover, takeover mode has some other limitations:
- Does not support TypeScript LS Plugin
- Features lag behind VSCode
- Every time the TS version is updated, performance regression might occur due to changes in the TS auto import cache code
- Difficult to implement invalidation of auto import cache
Since the TypeScript Vue Plugin can proxy TS functionalities, why not take over all TS functionalities for Vue files within the TypeScript Vue Plugin?
Given that TS support for Vue files is provided by the TS Server, and language features unrelated to TS (such as CSS, HTML, JSON) are provided by the Vue Language Server, we call this approach Hybrid Mode. (You can also think of it as an inverse takeover mode.)
The Vue Language Server no longer needs a TypeScript LS instance, thus achieving memory usage performance similar to Takeover Mode.
In August 2023, I first proposed the idea of addressing the problem in a new direction in version 2.0 and completed a PoC after 4 months of development.
In January 2024, we released Volar.js 2.0 to complete the infrastructure and refactoring needed for Hybrid Mode.
Finally, we implemented the TS plugin migration in one PR and were thrilled to find that it solved many of our problems!
Just when we thought everything was ready and set to release 2.0.0 in March, we hit the worst timing for a release.
Being the first language tool to fully adopt a TS plugin, we encountered many compatibility issues that were not discovered during our internal testing.
The worst part was one of the issues stemmed from a bug in the version of Node.js bundled with VSCode. We were in a completely passive situation for a month, waiting for VSCode to release an update with a new version of Node.js.
After I resolved all the stability issues I could reproduce, the user complaints did not stop. After going through this process for several months, I became possibly the first extension developer to suffer from depression due to developing a VSCode extension.
As of writing this article, the latest version is 2.0.26. Under normal circumstances, the performance should have significantly improved compared to v1, and the memory usage is even slightly lower than v1 Takeover Mode.
(Test results at https://github.com/elk-zone/elk)
TS Server | Vue Language Server | Total | |
---|---|---|---|
v1 without Takeover Mode | 516 MB | 541 MB + 197 MB | 1254 MB |
v1 with Takeover Mode | --- | 541 MB + 197 MB | 738 MB |
v2 with Hybrid Mode | 516 MB | 123 MB | 639 MB |
There were no other successful cases to refer to for full integration with the TS Server, everything had to be figured out on our own. Therefore, it took us 7 months, from August 2023 to March 2024, to land version 2.0.
Investing several months into a single task for an open-source project is a process that can easily lead to getting lost. During this time, I constantly experienced sleep deprivation and self-doubt, but fortunately, we persisted and completed it. Currently, more and more frameworks are migrating to full TS plugin integration through Volar.js, and I believe this is the right path to achieving the highest point of Developer Experience (DX) for all of us.
Besides the mental challenges, full-time open source is also an economic challenge. I have been thinking about how to improve the sustainability of open-source projects. This is not just about my personal income but also about how to fairly distribute sponsorships to contributors to motivate project development.
I do not want to force people to pay for open-source software, nor do I want to emotionally blackmail people into sponsoring, but rather aim to establish a fair trade that is fair to everyone. Therefore, we are now exploring a charging method that offers early access to features for sponsors. If you think this plan benefits you, please consider subscribing to it. (Spoiler: The Reactions Visualization feature is very useful.)
This article only introduced Hybrid Mode, but in reality, version 2.0 includes many powerful improvements, such as rewriting vue-tsc to significantly reduce memory usage, among other features. I hope to have the opportunity to introduce these to you in the future.
I want to give a huge thank you to StackBlitz, who have supported me in full-time development since the beginning of last year, making these world-improving changes possible.
Also, a big thank you to Astro and JetBrains for generously donating ten thousand dollars, allowing us to focus entirely on development without worrying about anything else.
(This space is reserved for our lovely supporters.)
❤️