December 01, 2021
Improving the Prisma Visual Studio Code Extension with WebAssembly
The Prisma Visual Studio Code extension is a key pillar of Prisma's developer experience. It enables you as a developer to rapidly iterate on your Prisma schema while giving you useful feedback about the correctness of the schema and automatic formatting. Today we're excited to share that we've improved the reliability of the extension by replacing the Prisma engine binary with a WebAssembly module that is natively cross-platform.
The Prisma schema
One of the key concepts that make Prisma unique compared to other database abstractions is the Prisma schema – a human-readable declarative representation of your data model. The Prisma schema is your primary touchpoint for database-related workflows like data modeling and the source of truth for a lot of Prisma's magic under the hood – automatically generating database migrations and the fully typed Prisma Client.
Schemas are a powerful concept in software development – they allow you to take a declarative approach and maintain a separation of concerns to a considerable degree by decoupling business logic from the shape of data.
Moreover, schemas have the property of being parsable, which opens the window to automated tooling that equips developers with a tight feedback loop informing you about errors in your schema, automatic formatting, and suggestions to avoid common pitfalls in your database schema design.
The Prisma schema language tries to strike the right balance between being self-explanatory and expressive. Self-explanatory means that even with no familiarity, you can still comprehend the data model, and expressive –in this context– means that you can effectively design your desired database schema without falling back to raw SQL (with relational databases).
The Prisma Visual Studio Code extension
To make it even easier to learn and evolve the Prisma schema, we've built the Prisma Visual Studio Code extension that helps create a tight feedback loop right within your code editor and has already been downloaded by over 170 thousand developers.
In essence, the Prisma VS Code extension removes much of the burden of learning yet another DSL (domain-specific language) with the following functionality:
Syntax highlighting
Formatting
Linting and autocompletion
Quick suggestions
Jump-to-definition
Anatomy of a language-specific Visual Studio Code extension
Visual Studio Code extensions use the Language Server Protocol (LSP) to standardize communication between language-specific tooling and the VS Code. This approach decouples the responsibilities into two parts:
- Language Client: Module in the Prisma VS Code extension (Node.js) that communicates using LSP with the Prisma Language Server.
- Language Server: A language analysis tool running in a separate process.
The benefit of this approach is that LSP-compliant extensions can be written in any language (e.g. Rust) for any language (e.g. the Prisma schema language). Separating the Language Server into a separate process ensures CPU-bound tasks don't slow down the editing experience.
Furthermore, the Language Server can be reused for multiple LSP-compliant code editors, which include Neovim, emacs and Atom, in addition to VS Code.
This allows VS Code extensions to implement language-specific autocomplete, error-checking, jump-to-definition, static analysis, and many other language features supported by VS Code.
Developer tooling with Rust at Prisma
At Prisma, we love Rust and use it to build much of Prisma's core functionality. Rust is a highly optimized systems programming language that can be compiled to binaries for multiple platforms.
For the VS Code plugin to provide useful feedback about your Prisma schema, we rely on the prisma-fmt
engine, which is written in Rust. The engine takes the Prisma schema as input, parses, formats it, performs static analysis (linting), and provides the formatted schema along with feedback such as errors and suggestions.
From a technical perspective, the Prisma VS Code extension has three main responsibilities:
- Define the Prisma schema language grammar for syntax highlighting.
- Downloading, starting, and managing the communication with the
prisma-fmt
engine binary. - Relay schema feedback data from
prisma-fmt
to VS Code through the Prisma Language Server, so it's visible to you.
Because the runtime for VS Code extensions is Node.js, while the prisma-fmt
engine is written in Rust, the Language Server code needs to start a side-car binary.
This approach introduces significant complexity:
- The Prisma engine binary must be compiled for each operating system which requires building and distribution infrastructure to ensure wide cross-platform support.
- Logic to download the correct binary at the initial runtime of the extension.
- Lifecycle management of the binary.
- Executing a downloaded binary can trigger user permission requests and false alarms by antivirus software that can scare users.
Historically we saw a cluster of problems that were difficult to reproduce and fix due to this complexity. This prompted us to research ways to simplify the extension codebase.
Introducing WebAssembly (Wasm)
WebAssembly is a new type of code that can be run in modern web browsers and Node.js — it is a low-level assembly-like language with a compact binary format that runs with near-native performance. Seeing as VS Code is built with Node.js,
WebAssembly is designed to run alongside JavaScript, allowing both to work together natively. Because the prisma-fmt
engine is written in Rust, it can also be compiled to WebAssembly, thanks to Rust's mature WebAssembly tooling. This means that WebAssembly modules can be imported natively into VS Code extensions.
Compiling the Prisma engine to a WebAssembly module instead of a platform-specific binary has several benefits:
- The Prisma engine (compiled into a Wasm module) can be packaged in the Prisma Language Server npm package, thereby simplifying distribution.
- Since WebAssembly is natively cross-platform compatible, we can do away with multiple compilation targets for
prisma-fmt
that were previously used by the Prisma Language Server (currently there are 22 compilation targets). - The Prisma Language Server doesn't need to download an additional binary after installation, potentially eliminating a whole class of errors.
Conclusion
The Prisma VS Code extension is a key pillar for Prisma's developer experience, creating a tight feedback loop as you design and evolve your Prisma schema.
Reducing the complexity of the underlying implementation can increase stability and allow us to introduce new features more rapidly.
WebAssembly has played a significant role in this, giving us seamless interoperability between Node.js and Rust code while simplifying and consolidating publishing with npm.
This is all cutting-edge technology. While it has passed rigorous testing internally and we're confident about its stability, such fundamental changes can introduce bugs. If you encounter any problems or bugs, be sure to open an issue.
For Prisma, this is exciting as it is the first time we deploy WebAssembly to production and opens the door to many other potential improvements.
Upgrade today
The new version of the Prisma extension for Visual Studio Code is available today as part of the 3.6.0
release.
Upgrade the extension in VS Code for the same developer experience you love.
Prisma is hiring
If you found this blog post interesting and want to work on the future of developer tools for databases, Prisma is hiring! Check out our current open positions.