Skip to content

Core Concepts ​

Understand the core design concepts of @meng-xi/vite-plugin, including the plugin system architecture, lifecycle, and common options.

Architecture Overview ​

┌─────────────────────────────────────────────────────┐
│                    User Project                      │
│  vite.config.ts                                     │
│    └─ plugins: [pluginA(), pluginB(), ...]          │
└──────────────────────┬──────────────────────────────┘
                       │
         ┌─────────────┴─────────────┐
         │   @meng-xi/vite-plugin    │
         ├───────────────────────────┤
         │  Built-in Plugins (17, 7) │
         │  ├─ compress (2)          │
         │  ├─ generate (5)          │
         │  ├─ inject (4)            │
         │  ├─ analyze (2)           │
         │  ├─ copy (2)              │
         │  ├─ guard (1)             │
         │  └─ proxy (1)             │
         ├───────────────────────────┤
         │  Plugin Framework          │
         │  ├─ BasePlugin             │
         │  ├─ createPluginFactory    │
         │  ├─ Logger                 │
         │  └─ Validator              │
         ├───────────────────────────┤
         │  Common Utils (14)         │
         └───────────────────────────┘

Plugin Groups ​

Plugins are grouped by functional verb, with each group representing a category of operations:

GroupSemanticsUse Case
compressCompressionReduce output size
generateGenerationAutomated code generation
injectInjectionInject content into HTML/runtime
analyzeAnalysisBuild process visualization
copyCopyOutput file management
guardGuardPre-build validation
proxyProxyDev server proxy

Plugin Lifecycle ​

All built-in plugins extend BasePlugin and follow a unified lifecycle:

Config Phase     Build Phase                  Output Phase
┌──────┐   ┌──────────────────┐   ┌──────────────────┐
│config│ → │configResolved    │ → │buildStart        │
│      │   │  (options merge)  │   │  transform       │
│      │   │  (validate)       │   │  resolveId/load  │
│      │   │  (initialize)     │   │  ...             │
└──────┘   └──────────────────┘   ├──────────────────┤
                                  │generateBundle    │
                                  │writeBundle       │
                                  │buildEnd          │
                                  ├──────────────────┤
                                  │closeBundle       │
                                  │  (destroy cleanup)│
                                  └──────────────────┘

Key Phases ​

PhaseHookDescription
ConfigconfigModify Vite config, return partial config
ResolvedconfigResolvedRead final config, initialize plugin state
BuildbuildStart / transformBuild start and code transformation
OutputgenerateBundle / writeBundleOutput generation and disk writing
EndbuildEnd / closeBundleBuild end and resource cleanup

Auto-handled by framework

BasePlugin automatically wraps configResolved and closeBundle to ensure enabled checks, error handling, and resource cleanup. Plugin developers only need to focus on business logic.

Common Options ​

All plugins share BasePluginOptions:

typescript
interface BasePluginOptions {
  /** Enable plugin, default true */
  enabled?: boolean
  /** Show verbose logs, default true */
  verbose?: boolean
  /** Error handling strategy, default 'throw' */
  errorStrategy?: 'throw' | 'log' | 'ignore'
}

enabled — Enable/Disable ​

typescript
compressAssets({
  algorithm: 'gzip',
  enabled: process.env.NODE_ENV === 'production'  // Only enable in production
})

verbose — Log Control ​

typescript
compressAssets({
  verbose: false  // Silent mode, no logs
})

errorStrategy — Error Handling ​

StrategyBehaviorUse Case
throwThrow exception, halt buildDevelopment (default)
logLog error, continue buildProduction (fault-tolerant)
ignoreSilent ignoreNon-critical plugins
typescript
imageOptimizer({
  errorStrategy: 'log'  // Image processing failure doesn't halt build
})

Error Handling Mechanism ​

BasePlugin provides safeExecute and safeExecuteSync methods to wrap plugin logic:

  • Sync hooks (config, transform) use safeExecuteSync
  • Async hooks (writeBundle, closeBundle) use safeExecute
  • Exceptions decide whether to halt build based on errorStrategy

Hook Protection

All hooks registered via registerHook / registerOrderedHook automatically get enabled checks and error wrapping. Directly assigned hooks (plugin.xxx = ...) need manual handling.

Logger System ​

Logger is a singleton, providing independent log proxies for each plugin instance:

typescript
// Auto-created by framework internally
this.logger.info('Compression complete')
this.logger.success('Processed 10 files')
this.logger.warn('File too large: main.js (2MB)')
this.logger.error('Compression failed: ' + error.message)

Each plugin instance has a unique identifier (pluginName#sequence), so log configs of multiple instances of the same type don't interfere with each other.

Configuration Validation ​

Validator provides a chainable API to validate config:

typescript
protected validateOptions(): void {
  this.validator
    .field('algorithm')
    .required()
    .enum(['gzip', 'brotli', 'both'])
    .validate()

  this.validator
    .field('threshold')
    .number()
    .minValue(0)
    .validate()
}

Next Steps ​

Released under the MIT License.