Application of build phase hooks
Basic Concepts of Build Phase Hooks
Vite.js build phase hooks allow developers to insert custom logic at different stages of the build process. These hooks are divided into two categories: build-time hooks and output generation hooks. Build-time hooks are triggered during module transformation and bundling, while output generation hooks execute when generating the final output.
// vite.config.js
export default defineConfig({
plugins: [
{
name: 'custom-hooks-plugin',
buildStart() {
console.log('Build started')
},
transform(code, id) {
if (id.endsWith('.vue')) {
// Special handling for Vue files
return modifyVueCode(code)
}
}
}
]
})
Detailed Explanation of Common Build Hooks
buildStart
Triggered at the start of the build, suitable for initialization operations. This hook receives an options
parameter containing build configuration information.
buildStart(options) {
console.log('Build options:', options)
this.startTime = Date.now()
}
resolveId
Used for custom module resolution logic. Returns null
to continue using the default resolver, or false
to exclude the module.
resolveId(source, importer, options) {
if (source === 'virtual-module') {
return '\0virtual-module' // Add virtual module marker
}
return null
}
load
Loads module content, often used with resolveId
to implement virtual modules.
load(id) {
if (id === '\0virtual-module') {
return 'export const msg = "From virtual module"'
}
return null
}
transform
Transforms module code, useful for modifying source code or adding additional functionality.
transform(code, id) {
if (id.endsWith('.js')) {
return code.replace(/console\.log\(.*?\)/g, '')
}
}
Output Generation Phase Hooks
renderStart
Triggered before generating output files, providing access to the final outputOptions
.
renderStart(outputOptions) {
console.log('Output directory:', outputOptions.dir)
}
generateBundle
Called before generating the bundle, allowing modification or addition of chunks.
generateBundle(options, bundle) {
for (const fileName in bundle) {
if (fileName.endsWith('.css')) {
const asset = bundle[fileName]
asset.source = minifyCSS(asset.source)
}
}
}
writeBundle
Triggered after files are written to disk, suitable for post-processing tasks.
writeBundle() {
console.log(`Build duration: ${Date.now() - this.startTime}ms`)
}
Advanced Use Cases
Custom File Processing
Combine multiple hooks to implement special file processing workflows:
{
name: 'markdown-loader',
transform(code, id) {
if (!id.endsWith('.md')) return
const html = markdownToHtml(code)
return `
<template>
<div class="markdown">${html}</div>
</template>
<style>
.markdown { /* styles */ }
</style>
`
}
}
Build Performance Monitoring
Use hooks to implement build process performance analysis:
{
name: 'build-perf',
buildStart() {
this.timings = {}
this.start('total')
},
buildEnd() {
this.end('total')
console.table(this.timings)
},
start(name) {
this.timings[name] = { start: performance.now() }
},
end(name) {
this.timings[name].end = performance.now()
this.timings[name].duration =
this.timings[name].end - this.timings[name].start
}
}
Multi-Environment Build Handling
Adjust build behavior based on environment variables:
{
name: 'env-config',
config(config, { mode }) {
if (mode === 'development') {
return { define: { __DEV__: true } }
}
},
transform(code, id) {
if (process.env.NODE_ENV === 'production') {
return code.replace(/mockData/g, 'realData')
}
}
}
Hook Execution Order and Dependency Management
Vite build hooks execute in a specific order, which is crucial for writing complex plugins:
options
- Modify or replace Rollup optionsbuildStart
- Build startsresolveId
- Resolve module IDsload
- Load module contenttransform
- Transform module codemoduleParsed
- Module parsing completedbuildEnd
- Build endsrenderStart
- Output generation beginsrenderChunk
- Process each chunkgenerateBundle
- Before generating bundlewriteBundle
- After files are written
Error Handling and Debugging Tips
Proper error handling in hooks improves build stability:
{
name: 'error-handler',
buildStart() {
try {
// Initialization operations
} catch (err) {
this.error('Initialization failed: ' + err.message)
}
},
transform(code, id) {
if (code.includes('deprecated')) {
this.warn(`Deprecated API found: ${id}`)
}
}
}
Add detailed logs for debugging:
{
transform(code, id) {
console.log(`Transforming file: ${id}`)
console.log('Original code:', code.slice(0, 100))
// Transformation logic
console.log('Transformed code:', result.slice(0, 100))
return result
}
}
Real-World Project Integration Examples
Automatic Route Configuration
Generate routes automatically with file system operations:
{
name: 'auto-routes',
buildStart() {
const pages = glob.sync('src/pages/**/*.vue')
const routes = pages.map(file => {
const path = file
.replace(/^src\/pages/, '')
.replace(/\.vue$/, '')
.replace(/\/index$/, '') || '/'
return {
path,
component: `() => import('${file}')`
}
})
fs.writeFileSync(
'src/routes.js',
`export default ${JSON.stringify(routes, null, 2)}`
)
}
}
Static Asset Versioning
Add hash versioning to static assets:
{
name: 'asset-version',
generateBundle(options, bundle) {
const hash = require('crypto')
.createHash('md5')
.update(Date.now().toString())
.digest('hex')
.slice(0, 8)
for (const fileName in bundle) {
if (fileName.endsWith('.js')) {
const asset = bundle[fileName]
asset.fileName = asset.fileName.replace(
/\.js$/,
`.${hash}.js`
)
}
}
}
}
Multi-Page Application Support
Extend Vite to support multi-page builds:
{
name: 'multi-page',
config(config) {
const pages = glob.sync('src/pages/**/main.js')
return {
build: {
rollupOptions: {
input: pages.reduce((entries, page) => {
const name = path.relative(
'src/pages',
path.dirname(page)
)
entries[name] = path.resolve(page)
return entries
}, {})
}
}
}
}
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn