Skip to content
第 131 / 250 章前端⏱ 10 分钟阅读

第 131 章:Vite 进阶配置

学习目标

  • 深入理解 Vite 的设计理念与优势
  • 掌握 Vite 常用插件与配置
  • 学会环境变量、路径别名、HMR 优化
  • 在项目中实现按需加载、CDN 注入

一、Vite 是什么

Vite(法语"快")是新一代前端构建工具,基于 ESBuild + Rollup,提供极速的开发体验。

1.1 开发 vs 生产

阶段工具特点
开发ESBuild极速冷启动,按需编译
生产Rollup完整打包,Tree-shaking

1.2 与 Webpack 对比

维度ViteWebpack
冷启动极快
HMR极快一般
配置简洁复杂
生态增长中成熟
插件Rollup 兼容丰富

二、项目初始化

2.1 create-vue

bash
pnpm create vue@latest

2.2 手动初始化

bash
pnpm init
pnpm add vue
pnpm add -D vite @vitejs/plugin-vue typescript vue-tsc

三、核心配置

3.1 vite.config.ts

typescript
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src')
    }
  },
  server: {
    port: 3000,
    open: true,
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        rewrite: (p) => p.replace(/^\/api/, '')
      }
    }
  },
  build: {
    outDir: 'dist',
    sourcemap: false,
    minify: 'esbuild',
    chunkSizeWarningLimit: 1500,
    rollupOptions: {
      output: {
        manualChunks: {
          'vue-vendor': ['vue', 'vue-router', 'pinia'],
          'ui-vendor': ['element-plus']
        }
      }
    }
  }
});

3.2 路径别名

typescript
import path from 'path';

export default defineConfig({
  resolve: {
    alias: {
      '@': path.resolve(__dirname, 'src'),
      '@components': path.resolve(__dirname, 'src/components'),
      '@utils': path.resolve(__dirname, 'src/utils')
    }
  }
});
typescript
// tsconfig.json
{
  "compilerOptions": {
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

四、环境变量

4.1 .env 文件

bash
# .env.development
VITE_API_URL=http://localhost:8080
VITE_APP_TITLE=Dev App

# .env.production
VITE_API_URL=https://api.example.com
VITE_APP_TITLE=Production App

4.2 在代码中使用

typescript
console.log(import.meta.env.VITE_API_URL);
console.log(import.meta.env.MODE);  // 'development' / 'production'
console.log(import.meta.env.DEV);   // boolean
console.log(import.meta.env.PROD);  // boolean

4.3 类型定义

typescript
// src/env.d.ts
/// <reference types="vite/client" />

interface ImportMetaEnv {
  readonly VITE_API_URL: string;
  readonly VITE_APP_TITLE: string;
}

interface ImportMeta {
  readonly env: ImportMetaEnv;
}

4.4 自定义 env 加载

typescript
// vite.config.ts
import { defineConfig, loadEnv } from 'vite';

export default defineConfig(({ mode }) => {
  const env = loadEnv(mode, process.cwd(), 'VITE_');
  return {
    define: {
      __APP_ENV__: env
    }
  };
});

五、服务器配置

5.1 基础

typescript
server: {
  host: '0.0.0.0',
  port: 3000,
  open: true,
  cors: true,
  strictPort: false
}

5.2 代理

typescript
server: {
  proxy: {
    '/api': {
      target: 'http://localhost:8080',
      changeOrigin: true,
      ws: true,
      rewrite: (path) => path.replace(/^\/api/, '')
    },
    '/socket.io': {
      target: 'ws://localhost:8080',
      ws: true
    }
  }
}

5.3 HMR 配置

typescript
server: {
  hmr: {
    protocol: 'ws',
    host: 'localhost',
    port: 5173,
    clientPort: 5173
  }
}

六、构建优化

6.1 拆分 chunk

typescript
build: {
  rollupOptions: {
    output: {
      manualChunks(id) {
        if (id.includes('node_modules')) {
          if (id.includes('vue') || id.includes('pinia')) {
            return 'vue-vendor';
          }
          if (id.includes('element-plus')) {
            return 'ui-vendor';
          }
          return 'vendor';
        }
      }
    }
  }
}

6.2 压缩

typescript
build: {
  minify: 'esbuild',  // 默认
  // 或 terser
  minify: 'terser',
  terserOptions: {
    compress: {
      drop_console: true,
      drop_debugger: true
    }
  }
}

6.3 静态资源

typescript
build: {
  assetsDir: 'static',
  assetsInlineLimit: 4096  // 4KB 以下内联
}

6.4 报告分析

bash
pnpm add -D rollup-plugin-visualizer
typescript
import { visualizer } from 'rollup-plugin-visualizer';

export default defineConfig({
  plugins: [
    visualizer({ open: true, gzipSize: true, brotliSize: true })
  ]
});

七、常用插件

7.1 Vue 官方

typescript
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [vue()]
});

7.2 自动导入

bash
pnpm add -D unplugin-auto-import unplugin-vue-components
typescript
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';

export default defineConfig({
  plugins: [
    AutoImport({
      imports: ['vue', 'vue-router', 'pinia'],
      resolvers: [ElementPlusResolver()],
      dts: 'auto-imports.d.ts'
    }),
    Components({
      resolvers: [ElementPlusResolver()],
      dts: 'components.d.ts'
    })
  ]
});

7.3 SVG 组件

bash
pnpm add -D vite-plugin-svg-icons
typescript
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';

export default defineConfig({
  plugins: [
    createSvgIconsPlugin({
      iconDirs: [path.resolve(__dirname, 'src/icons')],
      symbolId: 'icon-[dir]-[name]'
    })
  ]
});
vue
<template>
  <svg><use href="#icon-user" /></svg>
</template>

7.4 Mock

bash
pnpm add -D vite-plugin-mock
typescript
import { viteMockServe } from 'vite-plugin-mock';

export default defineConfig({
  plugins: [
    viteMockServe({
      mockPath: 'mock',
      enable: true
    })
  ]
});
typescript
// mock/user.ts
export default [
  {
    url: '/api/users',
    method: 'get',
    response: () => ({ data: [{ id: 1, name: 'Tom' }] })
  }
];

7.5 压缩

bash
pnpm add -D vite-plugin-compression
typescript
import compression from 'vite-plugin-compression';

export default defineConfig({
  plugins: [
    compression({
      algorithm: 'gzip',
      ext: '.gz',
      threshold: 10240
    })
  ]
});

八、加载优化

8.1 预构建

typescript
optimizeDeps: {
  include: ['vue', 'vue-router', 'pinia', 'axios'],
  exclude: ['some-large-lib']
}

8.2 CDN 注入

typescript
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [
    vue(),
    {
      name: 'html-transform',
      transformIndexHtml(html) {
        if (process.env.NODE_ENV === 'production') {
          return html.replace(
            '</head>',
            `
              <script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
            </head>`
          );
        }
        return html;
      }
    }
  ],
  build: {
    rollupOptions: {
      external: ['vue'],
      output: {
        globals: { vue: 'Vue' }
      }
    }
  }
});

8.3 动态导入

typescript
// 路由懒加载
const Dashboard = () => import('@/views/Dashboard.vue');

// 条件加载
button.addEventListener('click', async () => {
  const { default: Modal } = await import('@/components/Modal.vue');
});

九、SSR 配置

typescript
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [vue()],
  build: {
    ssr: true,
    rollupOptions: {
      input: 'src/entry-server.ts'
    }
  }
});
typescript
// src/entry-server.ts
import { createSSRApp } from 'vue';
import App from './App.vue';

export function createApp() {
  const app = createSSRApp(App);
  return { app };
}

十、库模式

typescript
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';

export default defineConfig({
  plugins: [vue()],
  build: {
    lib: {
      entry: path.resolve(__dirname, 'src/index.ts'),
      name: 'MyLib',
      fileName: (format) => `my-lib.${format}.js`,
      formats: ['es', 'cjs', 'umd']
    },
    rollupOptions: {
      external: ['vue'],
      output: {
        globals: { vue: 'Vue' }
      }
    }
  }
});
json
{
  "name": "my-lib",
  "files": ["dist"],
  "main": "./dist/my-lib.cjs.js",
  "module": "./dist/my-lib.es.js",
  "types": "./dist/index.d.ts"
}

十一、Monorepo 支持

typescript
// vite.config.ts
export default defineConfig({
  resolve: {
    alias: {
      '@my-ui/components': path.resolve(__dirname, '../packages/components/src'),
      '@my-ui/utils': path.resolve(__dirname, '../packages/utils/src')
    }
  },
  server: {
    fs: {
      allow: [path.resolve(__dirname, '..')]
    }
  }
});

十二、CSS 配置

12.1 CSS Modules

typescript
css: {
  modules: {
    localsConvention: 'camelCase',
    generateScopedName: '[name]__[local]___[hash:base64:5]'
  }
}
vue
<style module>
.box {
  color: red;
}
</style>

<template>
  <div :class="$style.box">...</div>
</template>

12.2 预处理器

bash
pnpm add -D sass
typescript
css: {
  preprocessorOptions: {
    scss: {
      additionalData: `@use "@/styles/variables.scss" as *;`
    }
  }
}

12.3 PostCSS

typescript
css: {
  postcss: {
    plugins: [
      autoprefixer(),
      cssnano()
    ]
  }
}

十三、调试

13.1 sourcemap

typescript
build: {
  sourcemap: true  // 或 'hidden'
}

13.2 调试 Vite 本身

bash
DEBUG=vite:* pnpm dev

13.3 插件 Hook

typescript
const myPlugin = {
  name: 'my-plugin',
  resolveId(id) {
    console.log('[resolveId]', id);
  },
  load(id) {
    console.log('[load]', id);
  }
};

十四、本章小结

概念关键
路径别名alias + tsconfig paths
环境变量.env + import.meta.env
代理server.proxy
构建rollupOptions.output
插件unplugin-* 系列
库模式build.lib
CSSmodules + preprocessor

动手练习

  1. 路径别名:配置 @ 指向 src 目录
  2. 环境变量:配置开发/生产环境的 API 地址
  3. 代理:配置跨域代理转发
  4. 自动导入:配置 unplugin-auto-import
  5. 构建优化:拆分 vendor chunk 并分析打包体积

推荐阅读


下一章第 132 章:ESLint 与 Prettier

本站基于 VitePress 构建 · 由 Codebook 团队维护