npm package: @kouovo/ph-webpack-plugin
Description: A Webpack plugin for watching file changes outside of the standard Webpack watch scope with customizable patterns and event handling.
Latest version: 0.1.46

# @kouovo/ph-webpack-plugin

A Webpack plugin for watching file changes outside of the standard Webpack watch scope with customizable patterns and event handling.

## Overview

The `@kouovo/ph-webpack-plugin` package provides a flexible file watching system for Webpack build processes. It allows you to monitor directories and files that are outside of Webpack's standard watch scope with customizable include/exclude patterns and event callbacks.

## Installation

```bash
npm install @kouovo/ph-webpack-plugin
# or
pnpm add @kouovo/ph-webpack-plugin
# or
yarn add @kouovo/ph-webpack-plugin
```

## Usage

### Basic Configuration

```typescript
import { WebpackWatcherPlugin } from '@kouovo/ph-webpack-plugin';

const config = {
  // ... other webpack configuration
  plugins: [
    new WebpackWatcherPlugin({
      watchDir: './src/assets',
      include: ['**/*.json', '**/*.md'],
      exclude: ['node_modules/**', 'dist/**'],
      onChange: (file, event) => {
        console.log(`File ${file} was ${event}`);
      },
    }),
  ],
};

export default config;
```

### Multiple Directories

```typescript
new WebpackWatcherPlugin({
  watchDir: ['./config', './data', './templates'],
  include: '**/*',
  exclude: ['**/*.log', '**/temp/**'],
  onChange: (file, event) => {
    if (event === 'change') {
      console.log(`Configuration updated: ${file}`);
    }
  }
})
```

### Advanced Usage with File Processor

```typescript
import { WebpackWatcherPlugin, createFileProcessor } from '@kouovo/ph-webpack-plugin';

const processor = createFileProcessor({
  onAdd: (file) => {
    console.log(`New file added: ${file}`);
    // Handle new file logic
  },
  onChange: (file) => {
    console.log(`File changed: ${file}`);
    // Handle file modification logic
  },
  onRemove: (file) => {
    console.log(`File removed: ${file}`);
    // Handle file removal logic
  },
  process: (file, event) => {
    // Custom processing logic for all events
    if (file.endsWith('.json')) {
      validateJsonFile(file);
    }
  }
});

const config = {
  // ... other webpack configuration
  plugins: [
    new WebpackWatcherPlugin({
      watchDir: ['./src/locales', './src/assets'],
      include: ['**/*.json', '**/*.png', '**/*.svg'],
      exclude: ['node_modules/**', 'dist/**', '**/*.test.*'],
      onChange: processor,
      enableLog: true,
      watchOptions: {
        awaitWriteFinish: {
          stabilityThreshold: 200,
          pollInterval: 20,
        },
      },
    }),
  ],
};

export default config;
```

## API Reference

### `WebpackWatcherPlugin`

A Webpack plugin class that watches external directories for file changes.

#### Constructor Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `watchDir` | `string \| string[]` | **Required** | Directory or directories to watch |
| `include` | `string \| string[]` | `'**/*'` | Glob patterns for files to include |
| `exclude` | `string \| string[]` | `'node_modules/**'` | Glob patterns for files to exclude |
| `onChange` | `(file: string, event: FileEvent) => void` | `() => {}` | Callback function for file changes |
| `watchOptions` | `chokidar.WatchOptions` | `{}` | Additional options for the underlying chokidar watcher |
| `enableLog` | `boolean` | `true` | Enable console logging for file events |

#### File Events

- `'add'` - A new file has been added
- `'change'` - An existing file has been modified
- `'unlink'` - A file has been removed

#### Example with Advanced Options

```typescript
new WebpackWatcherPlugin({
  watchDir: './config',
  include: '**/*.env',
  enableLog: false,
  watchOptions: {
    usePolling: true,
    interval: 1000,
    ignoreInitial: false,
    awaitWriteFinish: {
      stabilityThreshold: 300,
      pollInterval: 50
    }
  },
  onChange: (file, event) => {
    if (file.includes('.env')) {
      console.log(`Environment file ${event}: ${file}`);
      // Trigger webpack recompilation
    }
  }
})
```

### `createFileProcessor(options)`

Creates a file processor function with specific event handlers.

#### Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `process` | `(file: string, event: FileEvent) => void` | `() => {}` | General processor for all events |
| `onAdd` | `(file: string) => void` | `null` | Handler for file addition events |
| `onChange` | `(file: string) => void` | `null` | Handler for file modification events |
| `onRemove` | `(file: string) => void` | `null` | Handler for file removal events |

#### Example

```typescript
const processor = createFileProcessor({
  onAdd: (file) => {
    console.log(`📄 New file: ${path.basename(file)}`);
    // Index new file
    indexFile(file);
  },
  onChange: (file) => {
    console.log(`✏️ Modified: ${path.basename(file)}`);
    // Reprocess file
    processFile(file);
  },
  onRemove: (file) => {
    console.log(`🗑️ Removed: ${path.basename(file)}`);
    // Clean up references
    removeFromIndex(file);
  },
  process: (file, event) => {
    // Log all events with timestamp
    console.log(`[${new Date().toISOString()}] ${event.toUpperCase()}: ${file}`);
  }
});
```

## Features

### Webpack Integration
- **Hook Integration**: Integrates with Webpack's `watchRun`, `watchClose`, and `shutdown` hooks
- **Compilation Invalidation**: Automatically triggers Webpack recompilation on file changes
- **Context Awareness**: Respects Webpack's context configuration for path resolution

### Pattern Matching
- **Glob Patterns**: Uses micromatch for flexible file pattern matching
- **Include/Exclude**: Fine-grained control over which files to watch
- **Multiple Patterns**: Support for arrays of patterns for complex matching

### File Watching
- **Chokidar Integration**: Built on robust file watching library
- **Debouncing**: Built-in write stabilization to prevent duplicate events
- **Cross-Platform**: Works consistently across Windows, macOS, and Linux

### Performance
- **Efficient Watching**: Optimized for performance with configurable options
- **Memory Management**: Automatic cleanup when webpack compilation ends
- **Selective Processing**: Only processes files matching include patterns

## Use Cases

### Configuration Management
```typescript
new WebpackWatcherPlugin({
  watchDir: './config',
  include: ['*.json', '*.yaml', '*.env'],
  onChange: (file, event) => {
    if (event === 'change') {
      // Reload configuration and trigger rebuild
      reloadConfig(file);
      // The plugin automatically invalidates webpack compilation
    }
  }
})
```

### Asset Processing
```typescript
new WebpackWatcherPlugin({
  watchDir: './src/assets/raw',
  include: ['**/*.png', '**/*.jpg', '**/*.svg'],
  onChange: async (file, event) => {
    if (event === 'add' || event === 'change') {
      // Process and optimize images
      await optimizeImage(file);
      // Generate different sizes
      await generateImageSizes(file);
      // Webpack will automatically rebuild after this
    }
  }
})
```

### Template Compilation
```typescript
new WebpackWatcherPlugin({
  watchDir: './templates',
  include: ['**/*.hbs', '**/*.mustache'],
  onChange: async (file, event) => {
    if (event !== 'unlink') {
      // Compile templates
      await compileTemplate(file);
      // Update template cache
      updateTemplateCache(file);
    }
  }
})
```

### Locale File Management
```typescript
new WebpackWatcherPlugin({
  watchDir: './locales',
  include: '**/*.json',
  onChange: (file, event) => {
    // Regenerate locale bundles
    generateLocaleBundles();
    // The webpack compilation will be invalidated automatically
  }
})
```

## Webpack Integration Details

### Plugin Lifecycle

1. **Initialization**: Plugin is instantiated with configuration options
2. **Watch Start**: `watchRun` hook initializes the file watcher when webpack starts watching
3. **File Events**: Chokidar detects file changes and triggers callbacks
4. **Compilation Invalidation**: Changed files automatically trigger webpack recompilation
5. **Cleanup**: `watchClose` and `shutdown` hooks ensure proper watcher cleanup

### Compilation Integration

```typescript
// The plugin automatically integrates with webpack's compilation process
new WebpackWatcherPlugin({
  watchDir: './external-data',
  onChange: (file, event) => {
    // Your custom logic here
    processFile(file, event);
    
    // No need to manually trigger recompilation -
    // the plugin handles this automatically
  }
})
```

## Comparison with Vite Plugin

| Feature | Webpack Plugin | Vite Plugin |
|---------|----------------|-------------|
| **Architecture** | Webpack compilation hooks | Vite dev server integration |
| **Hot Reload** | Webpack invalidation | WebSocket integration |
| **Initialization** | `watchRun` hook | `configureServer` hook |
| **Cleanup** | `watchClose` + `shutdown` hooks | HTTP server close |
| **Build Integration** | Both build + watch modes | Development server only |
| **Recompilation** | Automatic via invalidation | Manual via WebSocket events |

## Error Handling

The plugin includes comprehensive error handling:

```typescript
new WebpackWatcherPlugin({
  watchDir: './config',
  onChange: (file, event) => {
    try {
      processFile(file, event);
    } catch (error) {
      console.error(`Error processing ${file}:`, error);
      // Handle error appropriately
    }
  },
  watchOptions: {
    // Chokidar will emit 'error' events which are logged by the plugin
  }
})
```

### Automatic Error Recovery

- **Watcher Errors**: Automatically logged and handled gracefully
- **File Processing Errors**: User callback errors don't crash the watcher
- **Cleanup Errors**: Proper cleanup even if errors occur during shutdown

## Performance Optimization

### Watch Options
```typescript
new WebpackWatcherPlugin({
  watchDir: './large-directory',
  watchOptions: {
    // Use polling for network drives
    usePolling: false,
    // Increase stability threshold for large files
    awaitWriteFinish: {
      stabilityThreshold: 300,
      pollInterval: 50
    },
    // Ignore initial scan for performance
    ignoreInitial: true
  }
})
```

### Selective Watching
```typescript
new WebpackWatcherPlugin({
  watchDir: './src',
  // Only watch specific file types
  include: ['**/*.json', '**/*.yaml'],
  // Exclude heavy directories
  exclude: [
    '**/node_modules/**',
    '**/dist/**',
    '**/.git/**',
    '**/coverage/**'
  ]
})
```

### Logging Control
```typescript
new WebpackWatcherPlugin({
  watchDir: './config',
  enableLog: process.env.NODE_ENV === 'development', // Only log in development
  onChange: (file, event) => {
    // Your logic here
  }
})
```

## TypeScript Support

The package includes full TypeScript support with exported types:

```typescript
import type { 
  WebpackWatcherPluginOptions, 
  FileEvent, 
  FileProcessorOptions 
} from '@kouovo/ph-webpack-plugin';

const options: WebpackWatcherPluginOptions = {
  watchDir: './data',
  include: '**/*.ts',
  onChange: (file: string, event: FileEvent) => {
    // Type-safe event handling
  }
};
```

## Dependencies

- **chokidar**: File watching with cross-platform support
- **micromatch**: Fast glob pattern matching
- **webpack**: Peer dependency for plugin integration

## License

MIT