Skip to content

Why reactive-vscode

VSCode extensions are powerful tools to enhance your development experience. But developing a VSCode extension is not easy. This library is created to help you develop a VSCode extension with Vue's reactivity system.

The Problems

Developing a VSCode extension is not easy. The official APIs are kind of primitive, which has several problems:

Hard to watch states

The official API is event-based, which means you have to listen to events to watch the state. This produces a lot of redundant code, and not familiar to Vue developers.

The Disposables

Disposables are everywhere in a VSCode extension. You have to store all of them to ExtensionContext.subscriptions, or dispose them manually.

When to Initialize

Views in a VSCode extension are created lazily. If you want to access a view instance, you have to store it, and even listen to a event which is fired when the view is created.

Want to use Vue

Vue's reactivity system is powerful. It's much easier to watch states and update views with Vue's reactivity system. But VSCode APIs are not designed to work with Vue.

The solution

Vue's Reactivity API is all you need. This library wraps most of the VSCode APIs into Vue Composables. You can use them as you use Vue Reactivity API, which is familiar to Vue developers.

With the help of this library, you can develop a VSCode extension just like developing a Vue 3 web application. You can use Vue's reactivity system to watch states, and implement views as Vue composables.

Result

Here is an example which shows how this library can help you develop a VSCode extension. The following extension decorates the active text editor depending on a configuration.

ts
import { 
defineConfigs
,
defineExtension
,
useActiveEditorDecorations
} from 'reactive-vscode'
const {
decorations
} =
defineConfigs
('demo', {
decorations
:
Boolean
})
export =
defineExtension
(() => {
useActiveEditorDecorations
(
{
backgroundColor
: 'red',
}, () =>
decorations
.
value
? [/* ... Caclulated ranges ... */] : [],
) })
ts
import type { ExtensionContext } from 'vscode'
import { window, workspace } from 'vscode'

const 
decorationType
= window.
createTextEditorDecorationType
({
backgroundColor
: 'red',
}) function
updateDecorations
(
enabled
: boolean) {
window.
activeTextEditor
?.
setDecorations
(
decorationType
,
enabled
? [/* ... Caclulated ranges ... */] : [],
) } export function
activate
(
context
: ExtensionContext) {
const
configurations
= workspace.
getConfiguration
('demo')
let
decorationsEnabled
=
configurations
.
get
<boolean>('decorations')!
context
.
subscriptions
.
push
(workspace.
onDidChangeConfiguration
((
e
) => {
if (
e
.
affectsConfiguration
('demo.decorations')) {
decorationsEnabled
=
configurations
.
get
<boolean>('decorations')!
updateDecorations
(
decorationsEnabled
)
} }))
context
.
subscriptions
.
push
(window.
onDidChangeActiveTextEditor
(() => {
updateDecorations
(
decorationsEnabled
)
}))
updateDecorations
(
decorationsEnabled
)
}

As you can see, after using reactive-vscode, the code is much cleaner and easier to understand. With composables like useActiveTextEditor provided by this library, you can use Vue's reactivity API like watchEffect smoothly when developing a VSCode extension.

More examples here.

FAQ

Vue without DOM and components?

This library is built on top of @vue/reactivity, and ported some code from @vue/runtime-core (See the ./packages/core/src/reactivity directory).

The size of the minimal extension built with this library is about 12KB.

Use Vue in Webview?

This library is not designed for using Vue in a webview. If you want to use Vue in a webview, you can use the CDN version of Vue or bundler plugins like @tomjs/vite-plugin-vscode.