Activation Events control when an extension is activated. They enable resource-efficient behavior through lazy-loading and targeted initialization only when actually needed. This system fundamentally differs from Eclipse plugins, which are typically loaded at IDE startup.
The following table shows the most important activation events and their typical use cases:
| Activation Event | Description | Typical Use Case |
|---|---|---|
onCommand:xyz |
Activates on command execution | User-initiated actions |
onLanguage:typescript |
Activates when opening specific file types | Language-specific tools |
workspaceContains:**/package.json |
Activates when specific files exist | Project-specific extensions |
onStartupFinished |
Activates after VSCode startup | Background services |
onFileSystem:ftp |
Activates for specific file system schemes | Remote file system providers |
* |
Activates at VSCode startup | Use only in exceptional cases |
The onCommand event is the most common activation
pattern. The extension is only loaded when the user triggers a specific
command:
// package.json - Extension manifest
{
"activationEvents": ["onCommand:myextension.analyze"],
"contributes": {
"commands": [{
"command": "myextension.analyze",
"title": "Analyze Code"
}]
}
}
// extension.ts - Implementation
export function activate(context: vscode.ExtensionContext) {
const command = vscode.commands.registerCommand(
'myextension.analyze',
async () => {
const editor = vscode.window.activeTextEditor;
if (!editor) {
vscode.window.showWarningMessage('No active editor');
return;
}
// Perform analysis
vscode.window.showInformationMessage('Analysis complete');
}
);
context.subscriptions.push(command);
}The onLanguage event automatically activates extensions
when files of specific languages are opened:
// package.json - Activation for TypeScript files
{
"activationEvents": ["onLanguage:typescript"]
}
// extension.ts - TypeScript-specific features
export function activate(context: vscode.ExtensionContext) {
// Register TypeScript-specific features
const provider = vscode.languages.registerCompletionItemProvider(
'typescript',
{
provideCompletionItems(document, position) {
const completion = new vscode.CompletionItem(
'interface',
vscode.CompletionItemKind.Snippet
);
completion.insertText = new vscode.SnippetString(
'interface ${1:Name} {\n\t${2:property}: ${3:type};\n}'
);
return [completion];
}
}
);
context.subscriptions.push(provider);
}workspaceContainsThe workspaceContains event allows activation based on
project structure. Extensions can detect different project types and
provide appropriate tools:
// package.json - Activation for Node.js and Docker projects
{
"activationEvents": [
"workspaceContains:**/package.json",
"workspaceContains:**/docker-compose.yml"
]
}
// extension.ts - Project type detection and integration
export async function activate(context: vscode.ExtensionContext) {
const workspaceFolders = vscode.workspace.workspaceFolders;
if (!workspaceFolders) return;
for (const folder of workspaceFolders) {
const projectTypes = await detectProjectTypes(folder.uri);
if (projectTypes.includes('nodejs')) {
setupNodeIntegration(context, folder.uri);
}
if (projectTypes.includes('docker')) {
setupDockerIntegration(context, folder.uri);
}
}
}
async function detectProjectTypes(workspaceUri: vscode.Uri): Promise<string[]> {
const types: string[] = [];
// Defined project indicators with improved typing
const indicators: ReadonlyArray<{ file: string; type: string }> = [
{ file: 'package.json', type: 'nodejs' },
{ file: 'docker-compose.yml', type: 'docker' }
];
for (const indicator of indicators) {
try {
const uri = vscode.Uri.joinPath(workspaceUri, indicator.file);
await vscode.workspace.fs.stat(uri);
types.push(indicator.type);
} catch {
// File does not exist
}
}
return types;
}Extensions can combine multiple activation events to implement flexible activation strategies:
// package.json - Multi-event configuration for test extension
{
"activationEvents": [
"onCommand:extension.runTests",
"onLanguage:javascript",
"onLanguage:typescript",
"workspaceContains:**/jest.config.js" // Jest test framework config
]
}This configuration activates the extension in the following scenarios: on direct command execution, when opening JavaScript/TypeScript files, or in projects with Jest configuration.
Avoid the * event: The universal
activation event "*" loads the extension at every VSCode
startup and should only be used in exceptional cases, as it affects
startup time.
Be specific: Choose the most specific event that
meets your needs. Instead of onLanguage:javascript for a
Node.js tool, use workspaceContains:**/package.json.
Use onStartupFinished sparingly: This
event is suitable for background services that are not immediately
needed. Use it only for non-critical functionality.
Conditional feature activation: Check the
environment in the activate() function and only register
supported features:
export function activate(context: vscode.ExtensionContext) {
// Check VSCode version
const hasNotebookAPI = vscode.version >= '1.60.0';
if (hasNotebookAPI) {
registerNotebookFeatures(context);
}
// Check extension dependencies
const pythonExt = vscode.extensions.getExtension('ms-python.python');
if (pythonExt?.isActive) {
registerPythonIntegration(context);
}
}VSCode provides several tools for analyzing extension behavior. The
Extension Bisect mode
(Developer: Reload With Extensions Disabled) helps identify
problematic extensions. The Developer Tools panel
(Help: Toggle Developer Tools) shows activation events in
the console. For detailed analysis, use the command
Developer: Show Running Extensions, which lists all active
extensions and their activation events.