The principle of Dependency Pre-Bundling
Principle of Dependency Pre-Bundling
Vite.js leverages native browser ES module support in development mode, serving source files on demand. However, bare module imports (e.g., import vue from 'vue'
) can lead to a waterfall of browser requests. Dependency pre-bundling solves this by converting CommonJS/UMD dependencies into ESM format and merging them into a single file.
Pre-Bundling Trigger Mechanism
Pre-bundling is automatically triggered in the following scenarios:
- During the initial startup of the development server
- When dependencies in
node_modules
change - When the
node_modules/.vite
cache directory is manually deleted
// vite.config.js
export default {
optimizeDeps: {
// Dependencies forced to pre-bundle
include: ['lodash-es'],
// Dependencies excluded from pre-bundling
exclude: ['moment'],
// Disable pre-bundling
disabled: false
}
}
Core Pre-Bundling Process
-
Dependency Scanning: Identifies all bare module imports through static analysis
- Uses esbuild's scanner to quickly parse import statements
- Recursively analyzes all dependencies of entry files
-
Dependency Bundling:
- Bundles each dependency and its deep dependencies into a single ESM file
- Handles special format conversions (CommonJS → ESM)
- Applies minification optimizations
-
Cache Handling:
- Generates a content hash as a cache identifier
- Stores results in the
node_modules/.vite
directory - Reuses existing cache on subsequent startups
Technical Implementation Details
Dependency Graph Construction Algorithm
interface DepInfo {
id: string
imports: Set<string>
// Other metadata...
}
function scanImports(filePath: string): DepInfo {
// Leverages esbuild's parsing capabilities
const result = esbuild.buildSync({
entryPoints: [filePath],
bundle: true,
write: false,
metafile: true
})
return {
id: filePath,
imports: extractImports(result.metafile)
}
}
Module Format Conversion
Example of converting a CommonJS module:
// Before (CommonJS)
const _ = require('lodash')
module.exports = _.cloneDeep
// After (ESM)
import * as _ from 'lodash'
export default _.cloneDeep
Cache Invalidation Strategy
Vite uses multi-layer cache validation:
- Hash of the
dependencies
field inpackage.json
- Content hash of lock files (package-lock.json/yarn.lock)
- Hash of the
optimizeDeps
configuration in the config file
Performance Optimization Techniques
- Parallel Processing: Uses worker threads to process multiple dependencies in parallel
- Incremental Building: Only rebuilds changed dependencies
- Smart Caching: Persistent caching based on file content hashes
// Example of multi-threaded processing
const worker = new Worker('./pre-bundle-worker.js')
worker.postMessage({
dep: 'vue',
version: '3.2.0'
})
Handling Special Scenarios
Circular Dependency Resolution
// a.js
import { b } from './b'
export const a = b + 1
// b.js
import { a } from './a'
export const b = a || 0
// After pre-bundling:
const __a = { a: undefined }
const __b = { b: undefined }
__a.a = __b.b + 1
__b.b = __a.a || 0
export { __a as a, __b as b }
Dynamic Import Handling
// Original code
const module = await import('lodash-es')
// After pre-bundling
const module = await import('/node_modules/.vite/lodash-es.js')
Custom Pre-Bundling Configuration
Advanced configuration example:
// vite.config.js
export default {
optimizeDeps: {
// Custom entry files
entries: [
'src/main.js',
'!src/excluded.js'
],
// Custom esbuild plugins
esbuildOptions: {
plugins: [myEsbuildPlugin()]
},
// Force rebuild
force: process.env.FORCE_REBUILD === 'true'
}
}
Differences from Regular Bundling
- Development-Only: Used exclusively for development server acceleration
- Preserves Module Boundaries: Unlike production bundling, it doesn't fully flatten modules
- Omits Full Optimizations: Skips production optimizations like code splitting and Tree-shaking
Debugging the Pre-Bundling Process
Debugging information can be output via environment variables:
DEBUG=vite:deps vite
Example output:
vite:deps Pre-bundling dependencies: vue, lodash-es +12ms
vite:deps Cache hit: react, react-dom +4ms
vite:deps Rebuilding dependency: vue-router (version changed) +8ms
Analysis of Pre-Bundled Output
Example structure of generated cache files:
node_modules/.vite/
├── _metadata.json
├── vue.js
├── lodash-es.js
└── dep-hash.json
The _metadata.json
contains:
{
"hash": "a1b2c3d",
"browserHash": "e4f5g6h",
"optimized": {
"vue": {
"file": "/path/to/vue.js",
"src": "/path/to/node_modules/vue/dist/vue.runtime.esm-bundler.js",
"needsInterop": false
}
}
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:按需编译与文件转换流程
下一篇:热模块替换(HMR)的高效实现