Skip to content

6.16 vite ​

6.16.1 概述 ​

Vite 基于 Rollup(打包和模块化) 和 esbuild(预构建) 实现的构建工具

在开发时候: Vite 以原生 ESM 方式提供源码。这实际上是让浏览器接管了打包程序的部分工作:Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际使用时才会被处理。

在构建时,Vite 不会在生产构建中使用 esbuild 作为打包工具,而是使用 Rollup 作为打包工具。因为 Vite 目前的插件 API 与使用 esbuild 作为打包器并不兼容。后续 Rollup 会取代 Rollup 和 esbuild 作为打包器,并消除开发和构建之间的不一致性。

安装 ​

zsh
    pnpm install vite

项目创建 ​

zsh
    pnpm create vite

6.16.2 功能 ​

TypeScript ​

Vite 天然支持引入 .ts 文件。但 Vite 并不执行任何类型检查 .ts 文件,只会使用 esbuild 将 TypeScript 转译到 JavaScript。

详见:3.17.4 vite项目配置案例

JSX ​

.jsx 和 .tsx 文件同样开箱即用。JSX 的转译同样是通过 esbuild

CSS Modules ​

Vite 可以导入以.module.css为后缀的 CSS 文件

css
/* example.module.css */
.red {
  color: red;
}
js
import classes from './example.module.css'
document.getElementById('foo').className = classes.red

TIP

导入的CSS Modules样式会自动注入到页面中,可以通过 ?inline 参数来关闭(模块被导入,但是样式并没有被注入到页面)

js
import './foo.css' // 样式将会注入页面
import otherStyles from './bar.css?inline' // 样式不会注入页面

静态资源处理 ​

js
import imgUrl from './img.png'
document.getElementById('hero-img').src = imgUrl

// 显式加载资源为一个 URL
import assetAsURL from './asset.js?url'

// 以字符串形式加载资源
import assetAsString from './shader.glsl?raw'

// 加载为 Web Worker
import Worker from './worker.js?worker'

// 在构建时 Web Worker 内联为 base64 字符串
import InlineWorker from './worker.js?worker&inline'

JSON ​

js
// 导入整个对象
import json from './example.json'
// 对一个根字段使用具名导入 —— 有效帮助 treeshaking!
import { field } from './example.json'

Glob ​

Vite 支持使用特殊的 import.meta.glob 函数从文件系统导入多个模块

js
const modules = import.meta.glob('./dir/*.js')

// 使用
for (const path in modules) {
  modules[path]().then((mod) => {
    console.log(path, mod)
  })
}


// vite 编译后的代码
const modules = {
  './dir/foo.js': () => import('./dir/foo.js'),
  './dir/bar.js': () => import('./dir/bar.js'),
}
  • 默认导入的文件是懒加载的,如果想直接导入通过附加参数设置 eager: true
js
const modules = import.meta.glob('./dir/*.js', { eager: true })

// vite 编译后的代码
import * as __glob__0_0 from './dir/foo.js'
import * as __glob__0_1 from './dir/bar.js'
const modules = {
  './dir/foo.js': __glob__0_0,
  './dir/bar.js': __glob__0_1,
}
  • 多个匹配模式
js
// { as: 'url' } 还支持将资源作为 URL 加载。
const modules = import.meta.glob('./dir/*.js', { as: 'raw', eager: true }) 

// vite 编译后的代码
const modules = {
  './dir/foo.js': 'export default "foo"\n',
  './dir/bar.js': 'export default "bar"\n',
}
  • 多个匹配模式
js
const modules = import.meta.glob(['./dir/*.js', './another/*.js'])
  • 反面匹配模式
js
const modules = import.meta.glob(['./dir/*.js', '!**/bar.js'])
  • 具名导入
js
const modules = import.meta.glob('./dir/*.js', { import: 'setup' })
  • 自定义查询
js
const modules = import.meta.glob('./dir/*.js', {
  query: { foo: 'bar', bar: true },
})

// vite 编译后的代码
const modules = {
  './dir/foo.js': () => import('./dir/foo.js?foo=bar&bar=true'),
  './dir/bar.js': () => import('./dir/bar.js?foo=bar&bar=true'),
}

动态导入 ​

Vite 依赖 Rollup 的 dynamic-import-vars 插件解析动态导入,但该插件仅支持静态字面量或有限变量格式,若路径包含字符串模板、正则或复杂表达式,Vite 无法分析路径,导致构建失败或运行时模块加载失败。

js
const module = await import(`./dir/${file}.js`)

当动态导入路径包含以下情况时需使用 @vite-ignore/vite-ignore:

  • 字符串模板拼接路径:import(./pages/${page}/index.jsx)
  • 路径变量来自运行时计算(如用户输入、API 响应)
  • 路径结构过于复杂,超出 Rollup 解析限制(如多级嵌套目录)
js
// 原始代码(打包时报错)
const Component = () => import(`../pages/${routePath}/index.jsx`); 

// 修复后
/* @vite-ignore */
const Component = () => import(`../pages/${routePath}/index.jsx`);

// vite-ignore属性
<img src="./images${routePath}/vite-ignore.png" vite-ignore>

WebAssembly ​

Web Workers ​

  • 通过构造器导入
js
const worker = new Worker(new URL('./worker.js', import.meta.url))
  • 带有查询后缀的导入
js
import MyWorker from './worker?worker'

const worker = new MyWorker()

内容安全策略(CSP) ​

6.16.3 配置 ​

  • 基础场景
js
// command 命令mode 模式 ssrBuild是否是ssr
export default defineConfig(({ command, mode, ssrBuild }) => {
  if (command === 'serve') {
    return {
      // dev 独有配置
    }
  } else {
    // command === 'build'
    return {
      // build 独有配置
    }
  }
})

// 与vue/cli不同的是,vite默认不加载.env ,所以不能通过process.env.NODE_ENV获取环境,如果确实需要可以使用loadEnv加载指定.env文件

import { defineConfig, loadEnv } from 'vite'

export default defineConfig(({ command, mode }) => {
  // 根据当前工作目录中的 `mode` 加载 .env 文件
  // 设置第三个参数为 '' 来加载所有环境变量,而不管是否有 `VITE_` 前缀。
  const env = loadEnv(mode, process.cwd(), '')
  return {
    // vite 配置
    define: {
      __APP_ENV__: JSON.stringify(env.APP_ENV),
    },
  }
})
  • 异步场景
js
export default defineConfig(async ({ command, mode }) => {
  const data = await asyncFunction()
  return {
    // vite 配置
  }
})

通用配置项 ​

  • root:项目根目录
  • base:公共基础路径
  • mode:构建模式(默认 development)
  • define
  • plugins:需要用到的插件数组
  • publicDir:静态资源服务、目录
  • cacheDir:预构建缓存文件的目录
  • resolve.alias:别名
  • resolve.dedupe::
  • resolve.conditions:
  • resolve.mainFields:
  • resolve.browserField:
  • resolve.extensions:
  • resolve.preserveSymlinks:
  • css.modules:
  • css.postcss:
  • css.preprocessorOptions:
  • css.devSourcemap:
  • css.transformer:
  • css.lightningcss:
  • json.namedExports:
  • json.stringify:
  • esbuild: esbuild转换选项
  • assetsInclude:
  • logLevel:调整控制台输出的级别
  • customLogger:
  • clearScreen:设置项目重载的时候是否清空终端中打印的信息
  • envDir:.env 文件的目录
  • envPrefix:设置将环境变量暴雷给客户端源码(默认 VITE_)
  • appType应用类型

spa:单页应用
mpa:多页应用
custom:无页面应用

服务配置项 ​

  • server.host:服务器IP地址(默认 localhost)
  • server.port:服务器端口
  • server.strictPort:端口被占用后的行为
  • server.https:启用 TLS + HTTP/2
  • server.open:服务器启动自动打开浏览器
  • server.proxy:自定义代理
  • server.cors:跨域资源访问
  • server.headers:服务器headers
  • server.hmr:
  • server.watch:监听文件的修改自动编译
  • server.middlewareMode:
  • server.fs.strict:限制访问工作区root意外的文件
  • server.fs.allow:
  • server.fs.deny:
  • server.origin:
  • server.sourcemapIgnoreList:

构建配置项 ​

  • build.target:设置构建物的浏览器兼容目标
  • build.modulePreload:模块预加载
  • build.outDir:指定输出路径
  • build.assetsDir:指定静态资源输出路径
  • build.assetsInlineLimit:根据此阈值判断导入资源是否转译为base64 编码,以避免额外的 http 请求。0表示禁用此项。
  • build.cssCodeSplit:是否开启CSS 代码拆分功能
  • build.cssTarget:设置css的浏览器兼容目标
  • build.cssMinify:
  • build.sourcemap:是否生成 source map 文件
  • build.rollupOptions:Rollup转换选项
  • build.commonjsOptions:
  • build.dynamicImportVarsOptions:
  • build.lib:
  • build.manifest:是否生成 manifest.json 文件
  • build.ssrManifest:是否生成 SSR 的 manifest.json 文件
  • build.ssr:面向 SSR 进行构建
  • build.minify:
  • build.terserOptions:
  • build.write:
  • build.emptyOutDir:
  • build.copyPublicDir:
  • build.reportCompressedSize:
  • build.chunkSizeWarningLimit:
  • build.watch:是否开启 rollup 监听器

预判配置项 ​

  • preview.host:
  • preview.port:
  • preview.strictPort:
  • preview.https:
  • preview.open:
  • preview.proxy:
  • preview.cors:
  • preview.headers:

优化配置项 ​

  • optimizeDeps.entries:
  • optimizeDeps.exclude:
  • optimizeDeps.include:
  • optimizeDeps.esbuildOptions:
  • optimizeDeps.force:
  • optimizeDeps.disabled:
  • optimizeDeps.needsInterop:

SSR配置项 ​

Worker配置项 ​

环境变量和模式 ​

js
// .env
NODE_ENV='development'  // 运行模式 是 生产还是开发环境,默认是通过.env.development区分环境,也可以在这里修改
VITE_APP_BASE_URL='/dev-api'  // 基础路径
VITE_APP_BASE_NAME='vite测试项目' // 基础名称
  • 获取环境变量
js
import.meta.env 
// 响应
// {
//     "VITE_APP_BASE_URL": "/api",
//     "VITE_APP_BASE_NAME": "'vite测试项目'  // 基础名称",
//     "VITE_USER_NODE_ENV": "development",
//     "BASE_URL": "/",
//     "MODE": "development",
//     "DEV": true,
//     "PROD": false,
//     "SSR": false
// }

配置案例 ​

  • vite.config.js,基于ElementPlus
js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import path from 'path'

// https://vitejs.dev/config/

export default defineConfig({
  plugins: [
    vue(),
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
  base: './',
   //  构建
  build: {
    outDir: 'dist', //指定打包输出路径
    assetsDir: 'assets', //指定静态资源存放路径
    cssCodeSplit: true, //css代码拆分,禁用则所有样式保存在一个css里面
    sourcemap: false, //是否构建source map 文件

    // 生产环境取消 console
    minify: 'terser',
    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true
      }
    },

    //会打包出 css js 等文件夹 目录显得清晰
    rollupOptions: {
      output: {
        chunkFileNames: 'js/[name]-[hash].js',
        entryFileNames: 'js/[name]-[hash].js',
        assetFileNames: '[ext]/[name]-[hash].[ext]'
      }
    }
  },
  server: {
    port: 9090,
    strictPort: true,
    cors: true,
    proxy: {
      '/api': {
        target: 'https://jaqi.gitee.io',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, 'database_json')
      },
    },
  },
  resolve: {
    alias: {
      vue: 'vue/dist/vue.esm-bundler.js',
      '@': path.resolve(__dirname, 'src'),
      '@views':path.resolve(__dirname, "src/views"),
      '@router': path.resolve(__dirname, "src/router"),
      '@store': path.resolve(__dirname, "src/store")
    }
  },
  css: {
    devSourcemap: true,
  },
})
  • package.json
js
{
  "name": "vite-project",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "serve:dev": "vite --mode development",
    "serve:prod": "vite --mode production",
    // serve 模式配置
    // --host [host]	指定主机名称 (string)
    // --port <port>	指定端口 (number)
    // --https	使用 TLS + HTTP/2 (boolean)
    // --open [path]	启动时打开浏览器 (boolean | string)
    // --cors	启用 CORS (boolean)
    // --strictPort	如果指定的端口已在使用中,则退出 (boolean)
    // --force	强制优化器忽略缓存并重新构建 (boolean)
    // -c, --config <file>	使用指定的配置文件 (string)
    // --base <path>	公共基础路径(默认为:/)(string)
    // -l, --logLevel <level>	Info | warn | error | silent (string)
    // --clearScreen	允许或禁用打印日志时清除屏幕 (boolean)
    // -d, --debug [feat]	显示调试日志 (string | boolean)
    // -f, --filter <filter>	过滤调试日志 (string)
    // -m, --mode <mode>	设置环境模式 (string)
    // -h, --help	显示可用的 CLI 选项
    // -v, --version	显示版本号
    // --profile 启动内置的 Node.js 调试器
    // --configLoader 使用 bundle 来采用 esbuild 打包配置,或是 runner(实验性)来在运行时处理,默认是 bundle
    "build": "vite build --mode production",
    // build 模式配置
    // --target <target>	编译目标(默认为:"modules")(string)
    // --outDir <dir>	输出目录(默认为:dist)(string)
    // --assetsDir <dir>	在输出目录下放置资源的目录(默认为:"assets")(string)
    // --assetsInlineLimit <number>	静态资源内联为 base64 编码的阈值,以字节为单位(默认为:4096)(number)
    // --ssr [entry]	为服务端渲染配置指定入口文件 (string)
    // --sourcemap [output]	构建后输出 source map 文件(默认为:false)(boolean | "inline" | "hidden")
    // --minify [minifier]	允许或禁用最小化混淆,或指定使用哪种混淆器(默认为:"esbuild")(boolean | "terser" | "esbuild")
    // --manifest [name]	构建后生成 manifest.json 文件 (boolean | string)
    // --ssrManifest [name]	构建后生成 SSR manifest.json 文件 (boolean | string)
    // --force	强制优化器忽略缓存并重新构建(实验性)(boolean)
    // --emptyOutDir	若输出目录在根目录外,强制清空输出目录 (boolean)
    // -w, --watch	在磁盘中模块发生变化时,重新构建 (boolean)
    // -c, --config <file>	使用指定的配置文件 (string)
    // --base <path>	公共基础路径(默认为:/)(string)
    // -l, --logLevel <level>	Info | warn | error | silent (string)
    // --clearScreen	允许或禁用打印日志时清除屏幕 (boolean)
    // -d, --debug [feat]	显示调试日志 (string | boolean)
    // -f, --filter <filter>	过滤调试日志 (string)
    // -m, --mode <mode>	设置环境模式 (string)
    // -h, --help	显示可用的 CLI 选项
    "preview": "vite preview"
    //  preview 模式配置
    // --host [host]	指定主机名称 (string)
    // --port <port>	指定端口 (number)
    // --strictPort	如果指定的端口已在使用中,则退出 (boolean)
    // --https	使用 TLS + HTTP/2 (boolean)
    // --open [path]	启动时打开浏览器 (boolean | string)
    // --outDir <dir>	输出目录(默认为:dist)(string)
    // -c, --config <file>	使用指定的配置文件 (string)
    // --base <path>	公共基础路径(默认为:/)(string)
    // -l, --logLevel <level>	Info | warn | error | silent (string)
    // --clearScreen	允许或禁用打印日志时清除屏幕 (boolean)
    // -d, --debug [feat]	显示调试日志 (string | boolean)
    // -f, --filter <filter>	过滤调试日志 (string)
    // -m, --mode <mode>	设置环境模式 (string)
    // -h, --help	显示可用的 CLI 选项
  },
  "dependencies": {
  },
  "devDependencies": {
  }
}

TIP

Vite 7.x