vue3+vite是目前比较成熟的框架。但是在生产环境还是有很多需要注意的地方。
根据 配置 Vite | Vite 官方中文文档 官方文档,主要可以优化的是打包文件大小,组织,兼容性等
经过实际测试可以配置以下选项,主要是build段落,比较坑的是目前很多框架提供的vite.config.js可能都不一定有build段落。
1、主要的配置是rollupOptions, 其中注意 input 就是应用入口,有些网上的配置的input是main.js对vue3应该不适用的,应该是 index.html位置才对。
input: {
main: path.resolve(__dirname, './index.html'),
},
2、rollupOptions, output 里面根据官方网站说明,对于打包引用的第三方node_modules,对js 以及静态资源进行拆分。
output: {
// 可以配置输出选项
manualChunks(id) {
if (id.includes("node_modules")) {
// 让每个插件都打包成独立的文件
return id .toString() .split("node_modules/")[1] .split("/")[0] .toString();
}
},
chunkFileNames: 'js/[name]-[hash].js', // 引入文件名的名称
entryFileNames: 'js/[name]-[hash].js', // 包的入口文件名称
assetFileNames: '[ext]/[name]-[hash].[ext]', // 资源文件像 字体,图片等
},
3、minify配置,minify可以设置为esbuild, terser, 或者 minify: false (就是输出的js不进行minify,如果打的包有问题可以设置为minify: false )
minify: 'terser', // 客户端默认构建是esbuild,需安装terser:`npm i -D terser`
terserOptions: {
// 生产环境移除console、debugger
compress: {
drop_console: false, // 默认false
drop_debugger: true, // 默认true
},
},
drop_console 这些是打包时去除调试信息,可以在正式运行时去掉,或者设置false保留控制台信息。
4、build段落 target ,参考官方说明 构建生产版本 | Vite 官方中文文档
target是比较重要的参数,参考官方设置。用以提高兼容性。
你也可以通过 build.target 配置项 指定构建目标,最低支持
es2015
。请注意,默认情况下 Vite 只处理语法转译,且 默认不包含任何 polyfill。你可以前往 Polyfill.io 查看,这是一个基于用户浏览器 User-Agent 字符串自动生成 polyfill 包的服务。
传统浏览器可以通过插件 @vitejs/plugin-legacy 来支持,它将自动生成传统版本的 chunk 及与其相对应 ES 语言特性方面的 polyfill。兼容版的 chunk 只会在不支持原生 ESM 的浏览器中进行按需加载。
一般情况下并不建议使用 @vitejs/plugin-legacy 来支持传统浏览器。
原因:
- legacy插件会导致打包文件增大,不符合生产环境优化。
- 根据vite文档,已经提供了target 提供浏览器兼容性,目前不支持现代javascript的浏览器比较少。所以一般尽量不使用legacy插件。
5、对于 vite-plugin-compression 插件的使用,有些框架会使用vite-plugin-compression用于打包时压缩静态资源如js、css,会压缩为.gz的压缩文件。该插件是否使用要结合实际考虑。
本人并没用使用 vite-plugin-compression,因为日常是使用nginx,nginx可以配置gzip,配置也比较简单,使用 vite-plugin-compression好像是多此一举。
6、关于 modulepreload 打包后会有一个比较大的js文件,css里面也有一个预加载的css文件,里面是预加载。
预加载是vite的一个优化机制,但是这个预加载的js文件又比较大,css的大小适中。
是不是使用预加载是一个纠结的问题,可以根据运行环境考虑。
如果要取消js的预加载(取消可以减少初次加载的js,减少网页卡的情况) 可以有两种方式
1种是取消js组件的所有预加载,2种是取消部分js组件的预加载
// 在 build: 段落增加以下配置
modulePreload: { // 取消js模块的预加载
resolveDependencies(filename, deps) {
return deps.filter(dep => !dep.endsWith('.js'))
}
},
7、增加把打包内容压缩成一个zip文件,便于日常上传更新操作
安装 vite-plugin-zip-pack
在vite.config 导入
npm i -D vite-plugin-zip-pack
import zipPack from "vite-plugin-zip-pack"
修改加入插件
plugins: [
......
zipPack({
inDir: 'dist',
// outDir: 'archive',
outFileName: `dist.zip`,
// pathPrefix: ''
})
8、以下是一个vite.config 主要打包的内容示例。
export default defineConfig(({ mode, command }) => {
return {
base: VITE_APP_ENV === 'production' ? '/' : '/',
plugins: createVitePlugins(env, command === 'build'),
resolve: {
// https://cn.vitejs.dev/config/#resolve-alias
alias: {
// 设置路径
'~': path.resolve(__dirname, './'),
// 设置别名
'@': path.resolve(__dirname, './src')
},
// https://cn.vitejs.dev/config/#resolve-extensions
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
},
// 输出目录
build: {
outDir: 'dist',
assetsDir: 'assets',
assetsInlineLimit: 4096,
cssCodeSplit: true,
sourcemap: false,
rollupOptions: {
//input: 'src/main.js',
input: {
main: path.resolve(__dirname, './index.html'),
},
output: {
// 可以配置输出选项
manualChunks(id) {
if (id.includes("node_modules")) {
// 让每个插件都打包成独立的文件
return id .toString() .split("node_modules/")[1] .split("/")[0] .toString();
}
},
chunkFileNames: 'js/[name]-[hash].js', // 引入文件名的名称
entryFileNames: 'js/[name]-[hash].js', // 包的入口文件名称
assetFileNames: '[ext]/[name]-[hash].[ext]', // 资源文件像 字体,图片等
},
},
minify: 'terser', // 客户端默认构建是esbuild,需安装terser:`npm i -D terser`
terserOptions: {
// 生产环境移除console、debugger
compress: {
drop_console: false, // 默认false
drop_debugger: true, // 默认true
},
},
chunkSizeWarningLimit: 500,
emptyOutDir: true,
manifest: false,
ssrManifest: false,
target: ["es2015"] // 'modules',// ["es2015", "chrome85"] // 'modules',
},
// vite 相关配置
server: {
port: 8080,
host: true,
open: true,
proxy: {
// https://cn.vitejs.dev/config/#server-proxy
'/dev-api': {
target: 'http://127.0.0.1:8082',
changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-api/, '')
}
}
},
//fix:error:stdin>:7356:1: warning: "@charset" must be the first rule in the file
css: {
postcss: {
plugins: [
{
postcssPlugin: 'internal:charset-removal',
AtRule: {
charset: (atRule) => {
if (atRule.name === 'charset') {
atRule.remove();
}
}
}
}
]
}
},
esbuild: {
// * 打包去除 console.log && debugger
pure: ["console.log", "debugger"]
}
}