vite和webpack的对比以及vite的常用配置

409 阅读5分钟

打包过程

vite先启动开发服务器=>请求模块时按需动态编译显示。遵循ES Modules模块规范来执行代码,不需打包编译成es5模块即可在浏览器运行。
webpack分析依赖=>编译打包=>交给本地服务器进行渲染。随着模块增多,打包的体积变大,造成热更新速度变慢。

vite启动时不需要分析各个模块之间的依赖关系,不需要打包编译,按需动态编译可缩短时间。可见当项目越复杂、模块越多的情况下,vite明显优于webpack。

底层语言

vite:基于esbuild预构建,esbuild是采用go语言编写的,而go语言是纳秒级别
webpack:基于node.js构建,js是以毫秒计数

所以,vite比webpack打包快10-100倍。

热更新

vite:浏览器重新请求该模块即可,故而热更新效率更高
webpack:模块以及模块依赖的模块需重新编译

适用场景

vite:适用于项目开发。是构建工具的高阶封装,使用起来简单且快。关注如何快读方便的搭建项目,相比webpack少了很多配置。
webpack:适用于工具开发。是静态模块打包工具,对整个应用及性能构建,重点放在构建上。关注的是各种功能的实现。

vite开发阶段打包快,但是相关生态没有webpack完善,vite可以作为开发的辅助。

可按以下几点进行vite的配置

  • 配置和pinia,router,axios,ref,reactive引入等等
  • 配置代理
  • 配置.ts,.vue,.tsx等等文件别名
  • 配置antdV按需加载
  • 配置antdV主题色+全局引入less+全局颜色变量
  • 配置vue使用tsx写法
  • 配置测试环境保留打印
结合当前项目,列举出一些常用配置,如下:
// import { fileURLToPath, URL } from "node:url";
import path, { resolve } from 'path';
import { visualizer } from 'rollup-plugin-visualizer'; // 可视化并分析您的 Rollup 捆绑包以查看哪些模块占用了空间
import { VitePlugin } from 'svg-preview-plugin';
import Unocss from 'unocss/vite';
import AutoImport from 'unplugin-auto-import/vite'; // 自动引入ref、reactive等等
import Components from 'unplugin-vue-components/vite'; // 配置antd-v按需加载
// import { AntDesignVueResolver } from "unplugin-vue-components/resolvers";
import { type ConfigEnv, type PluginOption, type UserConfig, defineConfig, loadEnv } from 'vite';
import importToCDN from 'vite-plugin-cdn-import';
import viteCompression from 'vite-plugin-compression';
import eslintPlugin from 'vite-plugin-eslint';
import { createHtmlPlugin } from 'vite-plugin-html';
// 当你使用该插件的时候,指定好存放svg的文件夹。再按照指定的方式去访问svg图片。就可以再不产生http请求的情况下渲染出svg图片。
// 在 main.js 中 import 'virtual:svg-icons-register'; // 引入svg icon注册脚本
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
import vueSetupExtend from 'vite-plugin-vue-setup-extend'; // 使 vue 脚本设置语法支持 name 属性。<script lang="ts" setup name="App"></script>

import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx'; // JSX语法编写组件

import { wrapperEnv } from './src/utils/getEnv';

// https://vitejs.dev/config/
export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
	const env = loadEnv(mode, process.cwd());
	const viteEnv = wrapperEnv(env); // 读取所有的环境变量配置

	return {
		base: '/', // 开发或生产环境服务的公共基础路径,默认"/"
		publicDir: resolve(__dirname, './dist'), // 默认public作为静态资源服务的文件夹
		assetsInclude: resolve(__dirname, './src/assets'), // 静态资源处理
		resolve: {
			alias: {
				// 别名配置
				'@': resolve(__dirname, './src'),
				'@assets': resolve(__dirname, './src/assets'),
				'@components': resolve(__dirname, './src/components'),
				'@views': resolve(__dirname, './src/views'),
				'@store': resolve(__dirname, './src/stores'), // "@": fileURLToPath(new URL("./src", import.meta.url)),
				'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js',
			},
		}, 
                // 打包去除 console.log && debugger
		esbuild: {
			pure: viteEnv.VITE_DROP_CONSOLE ? ['console.log', 'debugger'] : [],
		},
		build: {
			outDir: 'dist',
			assetsDir: 'assets', // 静态资源的存放路径文件名
			sourcemap: false,
			brotliSize: false, // 启用/禁止brotli压缩大小报告。禁用该功能可能会提高大型项目的构建性能
			minify: 'esbuild', // 项目压缩:boolean | "terser" | "esbuild" // minify: "terser", // esbuild 打包更快,但是不能去除 console.log,terser打包慢,但能去除 console.log // terserOptions: { //  compress: { //    drop_console: viteEnv.VITE_DROP_CONSOLE, //    drop_debugger: true //  } // },
			chunkSizeWarningLimit: 1500, // chunk大小警告的限制,默认500kb
			cssTarget: 'chrome61', // 防止vite将rgbs()颜色转化为#RGBA十六进制符号的形式(要兼容的场景是安卓微信中的webview时,不支持css中的#RGBA十六进制颜色符号) // esbuild打包更快,但是不能去除console.log,terser打包慢,但能去除console.log // minify: "terser", // terserOptions: { //   compress: { //     drop_console: viteEnv.console, //     drop_debugger: true, //   }, // },
			rollupOptions: {
				output: {
					// 静态资源分类和打包
					chunkFileNames: 'assets/js/[name]-[hash].js',
					entryFileNames: 'assets/js/[name]-[hash].js',
					assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
					manualChunks(id) {
						// 将pinia的全局库实例打包进verder(之后不同页面则按需加载),避免和页面一起打包造成资源重复引入
						if (id.includes(path.resolve(__dirname, 'src/stores/index.ts'))) {
							return 'verder';
						}
					},
				},
			},
		},
		css: {
			// css预处理器。全局变量+全局引入less+配置antdv主题色
			preprocessorOptions: {
				less: {
					javascriptEnabled: true, // 全局变量使用:@primary-color
					modifyVars: {
						'primary-color': '#1890ff', // 全局主色
						'link-color': '#1890ff', // 链接色
						'success-color': '#52c41a', // 成功色
						'warning-color': '#faad14', // 警告色
						'error-color': '#f5222d', // 错误色
						'font-size-base': '44px', // 主字号
						'heading-color': 'rgba(0, 0, 0, 0.85)', // 标题色
						'text-color': 'rgba(0, 0, 0, 0.65)', // 主文本色
						'text-color-secondary': 'rgba(0, 0, 0, 0.45)', // 次文本色
						'disabled-color': 'rgba(0, 0, 0, 0.25)', // 失效色
						'border-radius-base': '2px', // 组件/浮层圆角
						'border-color-base': '#d9d9d9', // 边框色
						'box-shadow-base': '0 2px 8px rgba(0, 0, 0, 0.15)', // 浮层阴影
					}, // modifyVars: { //  hack: `true; @import (reference) "${resolve('src/styles/var.less')}"`, // },
				},
			},
		},
		server: {
			// 服务器主机名,如果允许外部访问,可设置为"0.0.0.0"
			host: '0.0.0.0',
			port: viteEnv.VITE_PORT,
			open: viteEnv.VITE_OPEN, // 启动时是否在浏览器中自动打开
			cors: true, // 是否为开发服务器配置CORS // 代理跨域 // 跨域代理配置
			proxy: {
				'/test': 'http://xxxxxxxxxxxx', // 字符串简写
				'/sa': {
					target: 'http://xxxxxxxxxx',
					changeOrigin: true, // 是否跨域
					secure: false, // 如果是https接口,需要配置这个参数
					rewrite: path => path.replace(/^\/sa/, ''), // 重写接口的url
				},
			},
		},
		plugins: [
			vue(), // vite可以使用jsx/tsx语法
			vueJsx(), // name可以写在script标签上
			vueSetupExtend(), // Eslint报错信息显示在浏览器界面上
			eslintPlugin(), // 是否生成包预览(分析依赖包大小,方便做优化处理)
			visualizer(), // 使用gzip压缩
			viteCompression({
				verbose: true,
				disable: false,
				threshold: 10240,
				algorithm: 'gzip',
				ext: '.gz',
			}),
			Unocss(),
			VitePlugin({
				dirPath: resolve('src/assets/icons'),
				port: 3030,
				open: false, // 自动打开预览
				deep: true, // 是否递归显示 dirPath 里的 svg // 自定义复制内容 // formatName(name) { //  return `<MyIcon name="${name}" />`; // },
			}) as PluginOption,
			AutoImport({
				imports: [
					'vue',
					'vue-router',
					'pinia',
					{
						axios: [
							['default', 'axios'], // import {default as axios} from "axios"
						],
					},
				],
				dts: 'types/auto-import.d.ts', // 生成全局引入文件
			}),
			Components({
				resolvers: [
					// AntDesignVueResolver({
					//   importStyle: "less", // 修改antdv主题色
					// }),
				],
			}),
			createHtmlPlugin({
				inject: {
					data: {
						title: 'vue3+vite测试demo',
					},
				},
			}), 
                        // * 使用 svg 图标
			createSvgIconsPlugin({
				iconDirs: [resolve(process.cwd(), 'src/assets/icons')],
				symbolId: 'icon-[dir]-[name]',
			}), 
                        // * cdn 引入(vue按需引入会导致依赖vue的插件出现问题(列如:pinia/vuex))
			importToCDN({
				modules: [
					// {
					//  name: "vue",
					//  var: "Vue",
					//  path: "https://unpkg.com/vue@next"
					// },
					// 使用cdn引入element-plus时,开发环境还是需要在main.js中引入element-plus,可以不用引入css
					// {
					//  name: "element-plus",
					//  var: "ElementPlus",
					//  path: "https://unpkg.com/element-plus",
					//  css: "https://unpkg.com/element-plus/dist/index.css"
					// }
				],
			}),
		],
	};
});