VSCode Extensions are packaged as .vsix files -
ZIP-based archives containing all extension components. Comparable to
JAR files in Java, they contain both code and metadata:
extension.vsix
├── extension/ # Extension content
│ ├── package.json # Manifest
│ ├── out/ # Compiled TypeScript
│ ├── resources/ # Static resources
│ └── node_modules/ # Runtime dependencies
├── [Content_Types].xml # MIME type definitions
└── extension.vsixmanifest # Package metadata
The VSIX format is based on the Open Packaging Convention (OPC) standard, so VSIX files can be opened and inspected as ZIP archives.
The vsce (Visual Studio Code Extensions) tool is the
official packaging utility:
# Global installation
npm install -g @vscode/vsce
# Project-local installation (recommended for teams)
npm install --save-dev @vscode/vsceIntegrate into package.json as build script:
{
"scripts": {
"vscode:prepublish": "npm run compile",
"compile": "tsc -p ./",
"package": "vsce package",
"package:check": "vsce ls"
}
}All TypeScript files must be compiled before packaging:
# One-time compilation
npm run compile
# Watch mode for development
npm run watchOptimize tsconfig.json for production builds:
{
"compilerOptions": {
"module": "Node16",
"target": "ES2022",
"outDir": "out",
"rootDir": "src",
"sourceMap": false, // No sourcemaps in production
"declaration": false, // No .d.ts files
"removeComments": true, // Remove comments
"strict": true
},
"exclude": [
"node_modules",
".vscode-test",
"src/test" // Exclude tests
]
}The vscode:prepublish script is automatically executed
before each packaging:
{
"scripts": {
"vscode:prepublish": "npm run clean && npm run compile",
"clean": "rimraf out",
"compile": "tsc -p ./",
"lint": "eslint src --ext ts",
"test": "npm run compile && node ./out/test/runTest.js"
}
}# Standard VSIX creation
vsce package
# Output: my-extension-1.0.0.vsix# With specific version
vsce package 1.2.3
# Create pre-release version
vsce package --pre-release
# Detailed output
vsce package --verbose
# Only show package contents without creation
vsce ls
# Package statistics
vsce package --stats# Use specific output path
vsce package --out dist/
# With timestamp in name
vsce package --out "dist/$(date +%Y%m%d-%H%M%S)-extension.vsix"{
"name": "my-extension",
"displayName": "My Professional Extension",
"description": "Professional development tools for TypeScript",
"version": "1.0.0",
"engines": {
"vscode": "^1.102.0"
},
"categories": ["Programming Languages", "Other"],
"main": "./out/extension.js",
"icon": "resources/icon.png"
}The files array explicitly controls which files are
included in the VSIX:
{
"files": [
"out/**/*",
"resources/**/*",
"syntaxes/**/*",
"package.json",
"README.md",
"CHANGELOG.md",
"LICENSE"
]
}{
"engines": {
"vscode": "^1.102.0", // Minimum VSCode version
"node": ">=18.0.0" // Node.js requirement
}
}Only dependencies are included in the VSIX package:
{
"dependencies": {
"axios": "^1.6.0", // Included in VSIX
"lodash": "^4.17.21" // Included in VSIX
},
"devDependencies": {
"@types/vscode": "^1.102.0", // Not in VSIX
"@types/node": "^20.0.0", // Not in VSIX
"@vscode/vsce": "^2.22.0", // Not in VSIX
"typescript": "^5.8.3" // Not in VSIX
}
}Webpack integration for optimized package size:
// webpack.config.js
const path = require('path');
module.exports = {
target: 'node',
mode: 'production',
entry: './src/extension.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'extension.js',
libraryTarget: 'commonjs2'
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: 'ts-loader'
}
]
},
externals: {
vscode: 'commonjs vscode' // Don't bundle VSCode API
},
optimization: {
minimize: true
}
};Package.json for Webpack build:
{
"main": "./dist/extension.js",
"scripts": {
"vscode:prepublish": "webpack --mode production",
"compile": "webpack --mode development",
"watch": "webpack --mode development --watch"
}
}Exclude files and folders from packaging:
# .vscodeignore - similar to .gitignore
.vscode/**
.git/**
src/**
**/*.ts
**/*.map
node_modules/**
*.vsix
.eslintrc.json
tsconfig.json
webpack.config.js
.github/**
**/*.test.js
coverage/**
{
"vsce": {
"dependencies": false, // Don't include node_modules
"yarn": false // Ignore yarn lock
}
}# List files that would be packaged
vsce ls
# With file sizes
vsce ls --size
# Show only specific file types
vsce ls | grep "\.js$"# Detailed package info
vsce package --stats
# Example output:
# Total files: 45
# Total size: 1.2 MB
# Largest files:
# out/extension.js (450 KB)
# node_modules/ (600 KB)# Open VSIX as ZIP and inspect
unzip -l my-extension-1.0.0.vsix
# Or with archive tools
7z l my-extension-1.0.0.vsixProblem: TypeScript compilation fails
# Show detailed TypeScript errors
npx tsc --noEmit --pretty
# Check specific files
npx tsc src/extension.ts --noEmitProblem: Dependencies not found
# Check node_modules status
npm ls --depth=0
# Install missing dependencies
npm install
# Analyze dependency tree
npm ls --allProblem: VSIX file too large (>50MB)
# Identify largest files
vsce ls --size | sort -k2 -hr | head -10
# Analyze node_modules if included
du -sh node_modules/* | sort -hrSolution: Webpack bundling or reduce dependencies
# Find unused dependencies
npm install -g depcheck
depcheck
# Tree-shaking with Webpack
npm run compile:webpackProblem: Package.json validation errors
# vsce validate (available from vsce 2.15)
vsce package --no-dependencies --dry-run
# Check package.json syntax
node -e "JSON.parse(require('fs').readFileSync('package.json', 'utf8'))"Problem: Engine version conflicts
{
"engines": {
"vscode": "^1.102.0" // Version too new?
}
}Test with different VSCode versions:
# Test with VSCode Insiders
code-insiders --install-extension my-extension.vsix
# Check compatibility
vsce verify my-extension.vsix{
"scripts": {
"prebuild": "npm run clean && npm run lint",
"build": "npm run compile",
"postbuild": "npm run test",
"package": "npm run build && vsce package",
"package:dev": "vsce package --pre-release",
"package:prod": "npm run package --no-dev"
}
}VSIX packaging is the critical transition from development to distribution. With proper configuration of TypeScript build, dependency management, and package exclusions, you create optimized, functional extension packages for further distribution.