Skip to content
Back to skills

2492 Build Config 5e1b2408

ASecurity

Complete build configurations for VS Code extensions.

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
developmentjavascripttypescriptjavareactnodetestingdebugginggitapidocumentation

Works with

  • vscode
  • api

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 2492-build-config_5e1b2408 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 2492 Build Config 5e1b2408?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 2492 Build Config 5e1b2408
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-2492-build-config-5e1b2408/badge)](https://www.skillsdirectory.com/skills/tools-only-2492-build-config-5e1b2408)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Build Configuration

Complete build configurations for VS Code extensions.

## Table of Contents

- [esbuild (Extension)](#esbuild-extension)
- [Vite (Webview)](#vite-webview)
- [TypeScript Configuration](#typescript-configuration)
- [Package Scripts](#package-scripts)
- [Development Workflow](#development-workflow)

---

## esbuild (Extension)

Use esbuild for the extension code (Node.js runtime).

### esbuild.js

```javascript
const esbuild = require('esbuild');
const { resolve } = require('path');

const isWatch = process.argv.includes('--watch');
const isProduction = process.argv.includes('--production');

/** @type {esbuild.BuildOptions} */
const buildOptions = {
  entryPoints: ['src/extension.ts'],
  bundle: true,
  outfile: 'dist/extension.js',
  external: [
    'vscode',  // VS Code API provided at runtime
    // Add other externals if needed (native modules, etc.)
  ],
  format: 'cjs',
  platform: 'node',
  target: 'node18',
  sourcemap: !isProduction,
  minify: isProduction,
  treeShaking: true,
  logLevel: 'info',

  // Handle __dirname in bundled code
  define: {
    'process.env.NODE_ENV': isProduction ? '"production"' : '"development"'
  },

  // Copy static assets
  loader: {
    '.node': 'copy',  // Native modules
  },

  // Plugins (optional)
  plugins: []
};

async function build() {
  if (isWatch) {
    const ctx = await esbuild.context(buildOptions);
    await ctx.watch();
    console.log('Watching for changes...');
  } else {
    await esbuild.build(buildOptions);
    console.log('Build complete');
  }
}

build().catch(() => process.exit(1));
```

### Multi-Entry Build

For extensions with multiple entry points:

```javascript
const buildOptions = {
  entryPoints: {
    extension: 'src/extension.ts',
    server: 'src/server.ts',  // Language server, etc.
  },
  outdir: 'dist',
  // ... rest of config
};
```

---

## Vite (Webview)

Use Vite for webview code (browser runtime).

### vite.config.ts

```typescript
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { resolve } from 'path';

export default defineConfig({
  plugins: [react()],

  root: resolve(__dirname),

  build: {
    outDir: resolve(__dirname, '../../dist/webview'),
    emptyOutDir: true,
    sourcemap: true,

    rollupOptions: {
      input: resolve(__dirname, 'index.html'),
      output: {
        // Consistent filenames (no hashes) for CSP
        entryFileNames: '[name].js',
        chunkFileNames: '[name].js',
        assetFileNames: '[name].[ext]'
      }
    },

    // Don't split chunks (simpler for extension)
    cssCodeSplit: false,

    // Inline small assets
    assetsInlineLimit: 4096,
  },

  // Resolve aliases
  resolve: {
    alias: {
      '@': resolve(__dirname, 'src')
    }
  },

  // Define globals
  define: {
    'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'production')
  },

  // Dev server (for standalone testing)
  server: {
    port: 3000,
    strictPort: true
  }
});
```

### Webview HTML Template

```html
<!-- src/webview/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Webview</title>
</head>
<body>
  <div id="root"></div>
  <script type="module" src="./index.tsx"></script>
</body>
</html>
```

---

## TypeScript Configuration

### tsconfig.json (Extension)

```json
{
  "compilerOptions": {
    "module": "commonjs",
    "target": "ES2022",
    "lib": ["ES2022"],
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,

    // Path aliases (optional)
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "src/webview"]
}
```

### tsconfig.json (Webview)

```json
{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "jsx": "react-jsx",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,

    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"]
    }
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}
```

---

## Package Scripts

### package.json

```json
{
  "scripts": {
    "vscode:prepublish": "npm run build",

    "build": "npm run build:extension && npm run build:webview",
    "build:extension": "node esbuild.js --production",
    "build:webview": "cd src/webview && vite build",

    "watch": "npm-run-all --parallel watch:*",
    "watch:extension": "node esbuild.js --watch",
    "watch:webview": "cd src/webview && vite build --watch",

    "compile": "npm run build:extension && npm run build:webview",

    "lint": "eslint src --ext ts,tsx",
    "lint:fix": "eslint src --ext ts,tsx --fix",

    "typecheck": "tsc --noEmit",
    "typecheck:webview": "cd src/webview && tsc --noEmit",

    "package": "vsce package",
    "publish": "vsce publish"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "@types/vscode": "^1.85.0",
    "@vitejs/plugin-react": "^4.2.0",
    "esbuild": "^0.20.0",
    "npm-run-all": "^4.1.5",
    "typescript": "^5.3.0",
    "vite": "^5.0.0",
    "@vscode/vsce": "^2.22.0"
  }
}
```

---

## Development Workflow

### Launch Configuration

Create `.vscode/launch.json`:

```json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Run Extension",
      "type": "extensionHost",
      "request": "launch",
      "args": [
        "--extensionDevelopmentPath=${workspaceFolder}"
      ],
      "outFiles": ["${workspaceFolder}/dist/**/*.js"],
      "preLaunchTask": "npm: watch"
    },
    {
      "name": "Run Extension (Production)",
      "type": "extensionHost",
      "request": "launch",
      "args": [
        "--extensionDevelopmentPath=${workspaceFolder}"
      ],
      "outFiles": ["${workspaceFolder}/dist/**/*.js"],
      "preLaunchTask": "npm: build"
    }
  ]
}
```

### Tasks Configuration

Create `.vscode/tasks.json`:

```json
{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "npm: watch",
      "type": "npm",
      "script": "watch",
      "isBackground": true,
      "problemMatcher": [
        "$tsc-watch",
        "$esbuild-watch"
      ],
      "presentation": {
        "reveal": "never",
        "panel": "dedicated"
      }
    },
    {
      "label": "npm: build",
      "type": "npm",
      "script": "build",
      "problemMatcher": ["$tsc", "$esbuild"]
    }
  ]
}
```

### Problem Matchers

Add to `.vscode/settings.json` for esbuild errors:

```json
{
  "typescript.tsc.autoDetect": "off"
}
```

### Development Steps

1. Open extension folder in VS Code
2. Run `npm install`
3. Press F5 to launch Extension Development Host
4. Make changes → extension reloads automatically (with watch)
5. Open Output panel → "Extension Host" for logs

### Debug Webview

1. In Extension Development Host, open Command Palette
2. Run "Developer: Toggle Developer Tools"
3. Switch to "Console" tab to see webview logs

Or use "Developer: Open Webview Developer Tools" when focused on a webview.

---

## .vscodeignore

Exclude unnecessary files from the packaged extension:

```
# Source files (compiled to dist/)
src/**
**/*.ts
tsconfig*.json

# Build tools
esbuild.js
vite.config.ts
.eslintrc*
.prettierrc*

# Dev files
.vscode/**
.github/**
node_modules/**

# Test files
**/*.test.ts
**/__tests__/**
coverage/**

# Documentation (optional)
docs/**
*.md
!README.md
!CHANGELOG.md
!LICENSE.md

# Git
.git/**
.gitignore

# Misc
**/*.map
.DS_Store
*.vsix
```

---

## Production Optimizations

### Minification

Already enabled in esbuild with `--production` flag.

### Tree Shaking

esbuild handles this automatically. Ensure:
- Use ES modules where possible
- Avoid `require()` for tree-shakeable imports
- Mark side-effect-free packages in package.json

### Bundle Analysis

```javascript
// Add to esbuild.js
const buildOptions = {
  // ...
  metafile: true,
};

const result = await esbuild.build(buildOptions);
const analysis = await esbuild.analyzeMetafile(result.metafile);
console.log(analysis);
```

### Source Maps in Production

For debugging published extensions:

```javascript
// esbuild.js
const buildOptions = {
  sourcemap: 'external',  // Separate .map files
  // or
  sourcemap: true,  // Inline (larger bundle)
};
```

Keep source maps but exclude from package:

```
# .vscodeignore
**/*.map
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.