vite常见面试题

3 阅读8分钟

1. Vite 是什么?有什么特点?

// Vite 的主要特点:
1. 开发服务器启动快(基于 ESM2. 热更新快(基于 ESM3. 按需编译
4. 内置对 TypeScriptJSXCSS 等的支持

2. Vite 和 Webpack 的区别

// Vite
- 开发环境下不打包,基于 ESM
- 生产环境使用 Rollup 打包
- 冷启动更快
- 热更新更快

// Webpack
- 开发环境下打包
- 全环境都需要打包
- 配置更灵活
- 生态更完善

3. Vite 的基本配置

// vite.config.js
// 1. 导入必要的模块
import { defineConfig } from 'vite'  // 导入 vite 配置函数,提供类型提示
import vue from '@vitejs/plugin-vue'  // 导入 vue 插件,用于处理 .vue 文件

export default defineConfig({
  // 2. 开发服务器配置
  server: {
    port: 3000,  // 设置开发服务器端口号为 3000
    proxy: {     // 设置代理,用于解决跨域问题
      '/api': {  // 当请求路径以 /api 开头时进行代理
        target: 'http://example.com',  // 代理目标地址
        changeOrigin: true  // 修改请求头中的 Origin,解决跨域问题
      }
    }
  },
  
  // 3. 构建配置
  build: {
    outDir: 'dist',     // 指定构建输出目录
    minify: 'terser'    // 使用 terser 进行代码压缩(比 esbuild 压缩更彻底)
  },
  
  // 4. 插件配置
  plugins: [
    vue()  // 使用 vue 插件,使 vite 能够处理 .vue 文件
  ],
  
  // 5. 路径解析配置
  resolve: {
    alias: {
      '@': '/src'  // 设置路径别名,@ 符号指向 src 目录,方便导入文件
    }
  }
})

4. Vite 的插件机制

// 自定义插件示例
export default function myPlugin() {
  // 返回一个插件对象
  return {
    // 插件名称,必须的属性,用于识别插件
    name: 'my-plugin',
    
    // buildStart 钩子:在构建开始时触发
    buildStart() {
      console.log('构建开始')
      // 这里可以做一些构建前的准备工作
      // 比如:创建目录、清理缓存等
    },
    
    // transform 钩子:用于转换代码
    // code: 源代码内容
    // id: 文件路径
    transform(code, id) {
      // 判断是否是 .vue 文件
      if (id.endsWith('.vue')) {
        // 返回转换后的代码
        return transformedCode  // 这里的 transformedCode 需要自己实现转换逻辑
      }
    }
  }
}

使用示例:

// vite.config.js
import myPlugin from './my-plugin'

export default defineConfig({
  plugins: [
    myPlugin()
  ]
})

5. Vite 的环境变量处理

// .env
VITE_API_URL=http://api.example.com

// .env.development
VITE_API_URL=http://dev-api.example.com

// 使用环境变量
console.log(import.meta.env.VITE_API_URL)

6. Vite 的 CSS 处理

// vite.config.js
export default defineConfig({
  css: {
    // CSS 预处理器配置
    preprocessorOptions: {
      scss: {
        // 自动导入全局 SCSS 变量文件
        // 这样在每个组件中都可以直接使用这些变量,而不需要手动导入
        additionalData: `@import "@/styles/variables.scss";`
      }
    },
    
    // CSS 模块化配置
    modules: {
      // 配置 CSS 模块的作用域行为
      scopeBehaviour: 'local',  // 'local' 表示启用局部作用域
      
      // 配置生成的类名格式
      localsConvention: 'camelCase'  // 将类名转换为驼峰命名
      // 例如:.my-class 在 JavaScript 中可以通过 styles.myClass 访问
    }
  }
})

主要功能:

  1. CSS 预处理器配置
  • 配置 SCSS 预处理器

  • 通过 additionalData 自动注入全局 SCSS 变量

  • 避免在每个组件中重复导入变量文件

  1. CSS 模块化配置
  • 启用 CSS 模块的局部作用域

  • 配置类名的生成规则

  • 支持驼峰命名方式访问类名

// @/styles/variables.scss
$primary-color: #1890ff;
$font-size: 14px;

// 组件中使用
<style lang="scss" module>
.myButton {
  // 可以直接使用 variables.scss 中的变量
  color: $primary-color;
  font-size: $font-size;
}
</style>

// 在 JavaScript 中使用
import styles from './style.module.scss'
// 可以通过 styles.myButton 访问类名

7. Vite 的构建优化

// vite.config.js
export default defineConfig({
  build: {
    // 1. Rollup 打包分块策略配置
    rollupOptions: {
      output: {
        manualChunks: {
          // 将 vue 相关的库打包到 vendor 块中
          vendor: ['vue', 'vue-router'],  
          // 将 lodash-es 打包到 utils 块中
          utils: ['lodash-es']
        }
      }
    },
    
    // 2. 代码压缩配置
    minify: 'terser',  // 使用 terser 作为压缩器
    terserOptions: {   // terser 的具体配置
      compress: {
        drop_console: true  // 删除代码中的 console.log 语句
      }
    }
  }
})

主要功能:

  1. 代码分块配置 (Code Splitting)

    • 使用 manualChunks 手动指定代码分块

    • vendor 块包含 Vue 核心库和路由

    • utils 块包含工具库

    • 这样可以更好地利用浏览器缓存,提高加载性能

  2. 代码压缩配置

    • 使用 terser 进行代码压缩

    • 配置 terser 删除所有 console.log 语句

    • 减小最终代码体积,提高生产环境性能

实际效果:

  • 生成的 dist 目录会包含多个 JS 文件:

    • vendor.[hash].js (Vue 相关代码)

    • utils.[hash].js (工具库代码)

    • 其他业务代码文件

  • 生产环境代码中不会有 console.log 语句

这种配置适合需要优化加载性能的中大型项目。

8. Vite 的静态资源处理

// 1. 不同类型的资源导入方式
// 图片导入 - 会被优化处理
import img from './img.png'  // 返回处理后的图片 URL

// URL 导入 - 直接获取文件 URL,不做处理
import url from './file.pdf?url'  // 添加 ?url 后缀表示直接获取 URL

// 原始内容导入 - 获取文件的原始内容
import text from './file.txt?raw'  // 添加 ?raw 后缀表示获取原始内容

// 2. Vite 配置
export default defineConfig({
  // 配置额外的静态资源类型
  assetsInclude: ['**/*.gltf'],  // 将 .gltf 文件作为静态资源处理
  
  build: {
    // 小于 4kb 的资源将被转为 base64 内联
    assetsInlineLimit: 4096  // 单位为字节(byte)
  }
})

主要功能:

  1. 资源导入方式
  • 普通导入:自动优化和处理资源

  • URL 导入:直接获取资源 URL

  • 原始导入:获取资源的原始内容

  1. 资源处理配置
  • assetsInclude:指定额外的静态资源类型

  • assetsInlineLimit:控制资源内联的大小阈值

使用示例:

// 在组件中使用
export default {
  setup() {
    return {
      // 使用导入的资源
      image: img,          // 图片 URL
      pdfUrl: url,        // PDF 文件 URL
      content: text       // 文本内容
    }
  }
}

9. Vite 的 HMR(热更新)

// 自定义 HMR 处理
if (import.meta.hot) {  // 检查是否支持热更新
  // accept 方法:接受模块更新
  import.meta.hot.accept((newModule) => {
    // newModule 是更新后的模块
    // 这里可以处理模块更新后的逻辑
    // 例如:更新组件、重新渲染等
  })
  
  // dispose 方法:模块被替换前的清理
  import.meta.hot.dispose(() => {
    // 在模块被替换前执行清理工作
    // 例如:
    // - 移除事件监听器
    // - 清除定时器
    // - 清理缓存
    // - 断开 WebSocket 连接等
  })
}

具体使用示例:

// 计数器组件示例
let count = 0
const counter = document.getElementById('counter')

// 更新显示
const updateCounter = () => {
  counter.textContent = count
}

if (import.meta.hot) {
  // 当模块更新时
  import.meta.hot.accept((newModule) => {
    // 保持状态,使用新的逻辑
    count = newModule.count
    updateCounter()
  })

  // 模块卸载前清理
  import.meta.hot.dispose(() => {
    // 清理可能的副作用
    counter.remove()
  })
}

主要功能:

  1. 热更新检测

    • if (import.meta.hot) 检查环境是否支持热更新

    • 通常在开发环境中可用

  2. 更新处理

    • accept 方法处理模块更新

    • 可以保持应用状态

    • 实现平滑更新

  3. 清理工作

    • dispose 方法在模块替换前执行清理

    • 防止内存泄漏

    • 确保应用状态的正确性

这种机制可以在开发时实现代码更新而无需刷新整个页面,提高开发效率。

10. Vite 的性能优化

1. 依赖预构建配置

export default defineConfig({
  optimizeDeps: {
    // 指定需要预构建的依赖
    include: [
      'lodash-es',  // 预构建 lodash-es
      'vue'         // 预构建 vue
    ]
  }
})

作用说明:

  • 将 CommonJS/UMD 转换为 ESM 格式

  • 将有许多内部模块的依赖关系转换为单个模块

  • 提高开发服务器的页面加载速度

2. 生产环境优化配置

export default defineConfig({
  build: {
    target: 'es2015',    // 设置目标浏览器的 JavaScript 版本
    minify: 'terser',    // 使用 terser 进行代码压缩
    cssCodeSplit: true,  // 启用 CSS 代码分割
    chunkSizeWarningLimit: 500  // 设置 chunk 大小警告的限制(单位:kb)
  }
})

配置说明:

  1. target: 指定生成代码的目标环境

  2. minify: 指定代码压缩方式

  3. cssCodeSplit: 控制 CSS 代码分割

  4. chunkSizeWarningLimit: 设置代码分块大小警告的阈值

这些配置主要用于优化生产环境的构建结果,提高应用性能。

11. Vite 的常见问题处理

1. 跨域配置

export default defineConfig({
  server: {
    proxy: {
      '/api': {  // 匹配所有 /api 开头的请求
        target: 'http://example.com',  // 代理目标地址
        changeOrigin: true,  // 修改请求头中的 Origin
        rewrite: (path) => path.replace(/^\/api/, '')  // 重写请求路径
        // 例如:/api/users -> http://example.com/users
      }
    }
  }
})

2. 路径别名配置

import path from 'path'  // 需要先导入 path 模块

export default defineConfig({
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src')  // 将 @ 解析为 src 目录的绝对路径
    }
  }
})

功能说明:

  • 简化项目中的导入路径

  • @ 符号指向 src 目录

  • 使用 path.resolve 确保路径的正确性

// 使用别名导入
import Component from '@/components/Component.vue'
// 等同于
import Component from 'src/components/Component.vue'

12. Vite 的生产部署

1. 基本构建配置

export default defineConfig({
  // 配置基础公共路径
  base: '/app/',  // 部署时的基础路径,如:https://example.com/app/
  
  build: {
    outDir: 'dist',      // 指定构建输出目录
    assetsDir: 'assets'  // 指定静态资源存放目录,最终路径:dist/assets
  }
})

功能说明:

  • base: 设置部署时的基础路径

  • outDir: 指定构建产物的输出目录

  • assetsDir: 指定静态资源(如图片、CSS、JS)的存放目录

2. 多页面应用配置

import { resolve } from 'path'  // 需要先导入 path 模块

export default defineConfig({
  build: {
    rollupOptions: {
      input: {
        // 配置多个入口页面
        main: resolve(__dirname, 'index.html'),    // 主页面
        nested: resolve(__dirname, 'nested/index.html')  // 嵌套页面
      }
    }
  }
})

功能说明:

  • 配置多页面应用的入口文件

  • main: 指向主页面 HTML

  • nested: 指向其他页面 HTML

  • 使用 resolve 确保路径的正确解析

构建输出示例:

dist/
├── assets/
├── index.html
└── nested/
    └── index.html

13. 重要概念解释

1. 依赖预构建

  • 将 CommonJS/UMD 转换为 ESM

  • 将多个依赖合并

  • 提高页面加载性能

  • 按需加载

  • 开发环境下基于 ESM按需加载

  • 生产环境下基于 Rollup代码分割

  • HMR 原理

  • 基于 ESM 的模块热替换

  • 精确的更新范围

  • 快速的更新速度

  • 构建优化

  • Tree-shaking

  • 代码分割

  • 资源压缩