Bootstrap

第5章 Vite高级功能(一)


Vite 提供了许多高级功能,使开发者能够更灵活、高效地构建和优化项目。本章将深入探讨这些高级功能,包括别名与路径解析、代理与跨域配置、热模块替换 (HMR)、动态导入与代码分割、预构建与依赖优化。

1. 别名与路径解析

在大型项目中,使用路径别名可以使代码更简洁易读。Vite 支持通过 vite.config.js 文件配置路径别名。

1 配置别名

vite.config.js 中使用 resolve.alias 配置路径别名。

import { defineConfig } from 'vite'
import path from 'path'

export default defineConfig({
  resolve: {
    alias: {
      // '@' 将指向 'src' 目录
      '@': path.resolve(__dirname, 'src'),
      // 'components' 将指向 'src/components' 目录
      'components': path.resolve(__dirname, 'src/components')
    }
  }
})

2 使用别名

在代码中使用配置的路径别名:

// 使用 '@' 别名导入 src 目录下的模块
import utils from '@/utils'
// 使用 'components' 别名导入 src/components 目录下的模块
import MyComponent from 'components/MyComponent.vue'

export default {
  components: {
    MyComponent
  }
}

2 代理与跨域配置

在开发过程中,经常会遇到跨域请求的问题。Vite 提供了方便的代理配置,帮助开发者解决跨域问题。

2.1 配置代理

vite.config.js 中使用 server.proxy 配置代理:

import { defineConfig } from 'vite'

export default defineConfig({
  server: {
    proxy: {
      // 代理 /api 到 http://localhost:3000
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }
})

2.2 使用代理

在代码中发送请求:

import axios from 'axios'

axios.get('/api/users')
  .then(response => {
    console.log(response.data)
  })
  .catch(error => {
    console.error('Error fetching users:', error)
  })

上述配置中,所有发往 /api 的请求都会被代理到 http://localhost:3000,并移除路径中的 /api 前缀。

3 热模块替换 (HMR)

热模块替换 (HMR) 允许在应用运行时替换、添加或删除模块,而无需重新加载整个页面。Vite 内置 HMR 支持,使得开发体验更加流畅。

3.1 HMR 基本使用

Vite 默认启用了 HMR,你无需额外配置即可享受 HMR 带来的便利。以下是一个使用 HMR 的简单示例:

// src/main.js
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)
app.mount('#app')

// HMR 接口
if (import.meta.hot) {
  import.meta.hot.accept((newModule) => {
    app.unmount()
    app.mount('#app')
  })
}

3.2 HMR 高级使用

在复杂的应用中,你可能需要更细粒度的 HMR 控制。以下是一个处理局部模块更新的示例:

// src/store.js
import { reactive } from 'vue'

export const store = reactive({
  count: 0
})

// 处理 HMR
if (import.meta.hot) {
  import.meta.hot.accept((newModule) => {
    // 替换旧的 store
    Object.assign(store, newModule.store)
  })
}

4 动态导入与代码分割

动态导入和代码分割有助于优化应用的性能,减少初始加载时间。Vite 内置对动态导入的支持,使得实现代码分割变得非常简单。

4.1 动态导入

使用 import() 函数进行动态导入:

// src/main.js
document.getElementById('loadButton').addEventListener('click', async () => {
  const { greet } = await import('./utils.js')
  console.log(greet('Vite'))
})

4.2 代码分割

Vite 自动进行代码分割,将动态导入的模块分割到单独的文件中。你可以通过 build.rollupOptions 进行更细粒度的控制:

import { defineConfig } from 'vite'

export default defineConfig({
  build: {
    rollupOptions: {
      output: {
        // 手动控制代码分割
        manualChunks(id) {
          if (id.includes('node_modules')) {
            return 'vendor'
          }
        }
      }
    }
  }
})

5 预构建与依赖优化

Vite 使用 esbuild 对依赖进行预构建,提高开发服务器的启动速度和模块热更新速度。

5. 1预构建依赖

在首次启动开发服务器时,Vite 会自动预构建依赖。你可以在 vite.config.js 中通过 optimizeDeps 进行配置:

import { defineConfig } from 'vite'

export default defineConfig({
  optimizeDeps: {
    include: ['axios', 'lodash'],
    exclude: ['vue-demi']
  }
})

5.2 手动预构建依赖

如果需要手动预构建依赖,可以使用 Vite 提供的 optimize 命令:

npx vite optimize

5.3 调试预构建

在开发过程中,你可能需要调试预构建的依赖。可以通过 optimizeDeps.debug 选项启用调试模式:

import { defineConfig } from 'vite'

export default defineConfig({
  optimizeDeps: {
    debug: true
  }
})
;