Build Your First VSCode Extension

Rohan Mukherjee
The Startup
Published in
6 min readMay 30, 2020
Publicity 100

What is VSCode?

Since you’re here, I believe you would’ve heard of VSCode. If not, here’s what you need to know:

“Visual Studio Code is a source-code editor made by Microsoft for Windows, Linux and macOS. Features include support for debugging, syntax highlighting, intelligent code completion, snippets, code refactoring, and embedded Git.”

— Abraham Lincoln

Alright, now what is an extension?

“The features that Visual Studio Code includes out-of-the-box are just the start. VS Code extensions let you add languages, debuggers, and tools to your installation to support your development workflow.”

— Bill Gates

Requirements

To follow along with this article, you will need:

  • VSCode (of course)
  • npm and node installed
  • Basic knowledge of Typescript (or Javascript)

Getting Started

To set up a template, you could use tools such as yeoman and VS Code Extension Generator.

npm install -g yo generator-code

Now, type yo code in your terminal and answer the questions that follow to create a template. However, if you create the files from scratch, it will save you from having to remove some unnecessary files and comments.

I am going to follow the following directory structure for the project.

- package.json
- tsconfig.json
- .vscodeignore
- src/
- extension.ts
- .vscode/
- extension.json
- launch.json
- settings.json
- README.md

.vscodeignore is optional, though it’s recommended to add files and folders that aren’t required in the final extension, like tsconfig.json, to reduce the size of the final package.

package.json

The displayName and the description are in the VSCode Marketplace upon publishing the extension. contributes contains an array of commands that are contributed by the extension. Notice the command field in this array, since it will be referred to later. You can optionally have a snippets key which contains the language and the path to the json containing the snippets. The activationEvents stores an array of events that activate your extension. The event “*” means that it is activated by default. You can include strings like “onCommand:extension.hello” or “onLanguage:python” instead. When these strings activate the extension is pretty self-explanatory.

The package.json above also contains eslint for Typescript in the devDependencies, you can remove it if you don’t want to set up a linter. Here is a sample snippets extension.

.vscode/extension.json

.vscode/launch.json

This is the file which VSCode uses while launching it’s debugger, hence it’s pretty important. The preLaunchTask uses npm: build, so there needs to be a build script in package.json. If you’re using JS, you can remove this field.

tsconfig.json

src/extension.ts

With all the config set up, it’s now time to write some code.

The activate(context) function, as the name suggests, runs when the extension is activated. It takes context as a parameter, which is of type vscode.ExtensionContext. This context object has a key subscriptions which is an array of commands. These commands can be created using the vscode.command.registerCommand('command.name', callback) function. The name of the command passed here is the one that had been referred to in package.json, in contributes.commands. An example command hello has been shown above, you can add more commands in a similar fashion. Notice extension.hello is the same exact name as mentioned in package.json.

The deactivate() function runs when the extension is deactivated.

You can now use the VSCode API inside these callbacks to perform your intended actions. For example, vscode.window.showInformationMessage('Hello'); shows a message ‘Hello’ when the command is executed. By the way, the Command Palette in VSCode can be accessed with the help of the shortcut: Ctrl + Shift + P.

You can also register auto-completion providers using vscode.languages.registerCompletionItemProvider(selector, provider, ...triggerCharacters); function. Explore the VSCode API here.

How do I run my extension?

I’m glad you ask. You can simply press F5 to start a debugging session, or click the Debug option on the sidebar, and then click the Start Debugging button. Note that this is going to use the content in your .vscode folder, especially launch.json, hence if it throws errors, double-check the configurations in that folder. Logs in your code can be viewed in the debug console on your original VSCode window.

Publishing Your Extension

Why should I publish my extension?

“Once you have made a high-quality extension, you can publish it to the VS Code Extension Marketplace so others can find, download, and use your extension. Alternatively, you can package an extension into the installable VSIX format and share it with other users.”

— Freddie Mercury

Now that you know how to create your extension, it’s time to publish it. You need to create an account on the Visual Studio Marketplace. Once you create a publisher, you can install vsce, a command line tool to package and publish your extensions.

npm i -g vsce

This will globally install vsce on your computer.

vsce package

This will package your extension into a .vsix file, which is basically an extension of .zip with some additional headers. The files/folders added in the .vscodeignore are ignored during creation of this vsix. Note: Do not add the README.md to the .vscodeignore file, since the README contains the documentation that is displayed or your extension’s page in the marketplace. It is also preferable to add a CHANGELOG.md to track changes across versions. Here are some more things you should keep in mind:

  • If you’re using Typescript, you need not include your source in the package, hence you can add src/ to .vscodeignore. However, do not forget to execute npm run build before running vsce package, otherwise your dist folder won’t appear in the .vsix. You could do this by adding a vscode:prepublish script in your package.json scripts. Here’s an example.
  • Do NOT ignore the dist folder by mistake. Your TS code gets compiled to JS and is saved in this folder. This is the the folder that contains your extension, basically.
  • Check all the paths in your package.json map to valid files in the dist folder. Make sure that your output folder for npm run build is called dist.
  • If your project has any dependencies, remember to include node-modules in your package, so don’t add it to .vscodeignore. You can ignore the devDependencies and install just the dependencies by running npm install --only=production.

You can create a publisher using vsce create-publisher <publisher-name> or using the website. Generate a Personal Access Token.

Note: Make sure you select ‘All accessible organizations’ while generating your access token on https://dev.azure.com, otherwise it might return a 401 or 403 error response. my-extension.vsix can now be directly uploaded on https://marketplace.visualstudio.com/manage/publishers/<publisher-name>, or published using:

vsce publish -p $PERSONAL_ACCESS_TOKEN

Using this command, you can publish your extension, replacing $PERSONAL_ACCESS_TOKEN with your token. This command can also be used with CI/CD for automatic publishing, here’s an example. If you don’t want to provide the token every time, you can run vsce login.

Wrapping Up…

With the help of this article, you know how to get started on building a VSCode extension. Beyond this; the sky’s the limit. You can refer to the vscode-extension-samples repository if you’re not sure how to proceed with your idea.

“Conformity is the jailer of freedom and the enemy of growth.”

— Linus Torvalds

--

--