package.json as manifest analogous to
plugin.xml
In VSCode extensions, package.json serves as the central
manifest and defines metadata, dependencies, and extension-specific
configurations. Functionally, it corresponds to plugin.xml
from Eclipse plugin development but differs by using JSON syntax and npm
integration.
plugin.xmlWhile Eclipse plugins declare their configuration in XML-based
manifests, VSCode uses the npm standard format package.json
with extension-specific additions:
Eclipse plugin.xml (example):
<?xml version="1.0" encoding="UTF-8"?>
<plugin>
<extension point="org.eclipse.ui.commands">
<command id="com.example.hello" name="Hello Command"/>
</extension>
<extension point="org.eclipse.ui.handlers">
<handler commandId="com.example.hello" class="HelloHandler"/>
</extension>
</plugin>VSCode package.json (equivalent):
{
"contributes": {
"commands": [{
"command": "extension.hello",
"title": "Hello Command"
}]
},
"activationEvents": [
"onCommand:extension.hello"
]
}The package.json begins with standard npm metadata, also
used for regular Node.js packages:
{
"name": "my-extension",
"displayName": "My Extension",
"description": "Extension description",
"version": "1.0.0",
"publisher": "publisher-name",
"author": {
"name": "Author Name",
"email": "author@example.com"
},
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/user/repo"
},
"keywords": ["vscode", "extension"],
"categories": ["Other"]
}VSCode extends the npm schema with extension-specific fields:
engines.vscode: Minimum version of VSCodecategories: Categorization in the Extension
MarketplaceactivationEvents: Definition of activation
conditionsmain: Entry point of the extension (equivalent to the
bundle activator in Eclipse)contributes: Declaration of extension pointsThe engines field defines VSCode compatibility:
{
"engines": {
"vscode": "^1.74.0"
}
}This declaration corresponds to the Required-Bundle
directive in Eclipse manifests and ensures that the extension is only
activated in compatible VSCode versions. The caret symbol
(^) allows minor and patch updates, but blocks breaking
changes.
Activation events define when VSCode loads the extension. They
replace Eclipse’s Bundle-ActivationPolicy concept:
{
"activationEvents": [
"onCommand:extension.hello",
"onLanguage:typescript",
"workspaceContains:**/package.json",
"onFileSystem:sftp",
"onStartupFinished"
]
}Common activation events:
onCommand:*: When specific commands are executedonLanguage:*: When files of certain languages are
openedworkspaceContains:*: When specific files/patterns
existonFileSystem:*: When accessing specific
filesystems*: Immediate activation (performance-critical)The contributes section declares extension points and
corresponds to the <extension> elements in
Eclipse:
{
"contributes": {
"commands": [{
"command": "extension.hello",
"title": "Hello World",
"category": "Sample"
}],
"menus": {
"commandPalette": [{
"command": "extension.hello",
"when": "editorTextFocus"
}]
},
"keybindings": [{
"command": "extension.hello",
"key": "ctrl+f1",
"when": "editorTextFocus"
}],
"languages": [{
"id": "log",
"aliases": ["Log File", "log"],
"extensions": [".log"]
}],
"grammars": [{
"language": "log",
"scopeName": "text.log",
"path": "./syntaxes/log.tmLanguage.json"
}]
}
}Commands: Declaration of executable commands
"commands": [{
"command": "extension.commandId",
"title": "Command Title",
"category": "Category Name",
"icon": "$(symbol-file)"
}]Menus: Integration into VSCode menu structures
"menus": {
"editor/context": [{
"command": "extension.commandId",
"when": "resourceExtname == .ts",
"group": "navigation"
}]
}Configuration: Custom user settings
"configuration": {
"title": "My Extension",
"properties": {
"myExtension.enabled": {
"type": "boolean",
"default": true,
"description": "Enable the extension"
}
}
}Dependency management follows npm conventions:
{
"dependencies": {
"axios": "^1.0.0",
"lodash": "^4.17.21"
},
"devDependencies": {
"@types/vscode": "^1.74.0",
"@types/node": "16.x",
"typescript": "^4.9.4",
"@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0",
"eslint": "^8.28.0"
}
}Critical dependencies:
@types/vscode: TypeScript definitions for VSCode
APIstypescript: TypeScript compiler for transpilation@types/node: Node.js types for backend
functionalityThe scripts section defines build and development workflows:
{
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"pretest": "npm run compile && npm run lint",
"lint": "eslint src --ext ts",
"test": "node ./out/test/runTest.js",
"package": "vsce package",
"publish": "vsce publish"
}
}Important scripts:
vscode:prepublish: Pre-hook for extension
packagingcompile: TypeScript transpilationwatch: Continuous recompilation during developmenttest: Execution of extension tests| Aspect | Eclipse plugin.xml | VSCode package.json |
|---|---|---|
| Format | XML-based | JSON-based |
| Schema | OSGi-specific | npm standard extended |
| Dependency Management | Manifest headers | npm-integrated |
| Extension Points | XML attributes | JSON objects |
| Lifecycle | Bundle activator | activate/deactivate functions |
| Versioning | OSGi semantic versioning | npm semantic versioning |
VSCode validates package.json against an extension
schema. Development environments offer IntelliSense support via the
schema:
{
"$schema": "https://raw.githubusercontent.com/Microsoft/vscode/master/extensions/extension-manifest.schema.json"
}Namespace conventions: Extension IDs should use unique prefixes:
"commands": [{
"command": "mycompany.myextension.action"
}]Performance optimization: Use minimal activation events:
"activationEvents": [
"onLanguage:typescript"
]Complete metadata: Meaningful descriptions for marketplace visibility:
{
"description": "Detailed extension description",
"keywords": ["typescript", "intellisense", "productivity"],
"categories": ["Programming Languages"]
}