前置工具
打包体积分析器:rollup-plugin-visualizer是一个打包体积分析插件,对应webpack中的webpack-bundle-analyzer。配置好后运行构建命令会生成一个stats.html。
npm i rollup-plugin-visualizer -D
Pnpm add rollup-plugin-visualizer -D
在vite.config.js里面配置
import { visualizer } from 'rollup-plugin-visualizer'
plugins: [
visualizer({open: true})
]
打包完成后会生成并自动打开一个HTML文件,类似下图:
配置打包文件分类输出
将js,css这些资源目录分别打包到对应的文件夹下
build: {
rollupOptions: {
output: {
chunkFileNames: 'js/[name]-[hash].js', // 引入文件名的名称
entryFileNames: 'js/[name]-[hash].js', // 包的入口文件名称
assetFileNames: '[ext]/[name]-[hash].[ext]', // 资源文件像 字体,图片等
}
}
}
js最小拆分包
- 配置vite.config 的 output 属性
- 让打开那个页面,加载那个页面的js ,让之间的关联足够小
- 让打开那个页面,加载那个页面的js ,让之间的关联足够小
output: {
// 最小化拆分包
manualChunks(id) {
if (id.includes('node_modules')) {
return id.toString().split('node_modules/')[1].split('/')[0].toString();
}
}
},
代码压缩+剔除console+debugger
esbuild or terser, 默认启动的是 esbuild, esbuild,比 terser 快 20-40倍,压缩率只差 1%-2%。
esbuild:
只删除 console.log 和 ****debugger
import {defineConfig} from "vite";
export default defineConfig({
esbuild:{
pure: ['console.log'], // 删除 console.log
drop: ['debugger'], // 删除 debugger
}
})
删除所有的console语句和debugger,包括console.log、console.warn、console.error等。
import {defineConfig} from "vite";
export default defineConfig({
esbuild:{
drop: ['console,'debugger'], // 删除 所有的console 和 debugger
}
})
terser:
vite 4.X 版本已经不集成 terser,需要自行下载。
Pnpm add terser -D
npm i terser -D
只删除 console.log 和 ****debugger
import { defineConfig } from "vite";
export default defineConfig({
build: {
minify: 'terser', // 启用 terser 压缩
terserOptions: {
compress: {
pure_funcs: ['console.log'], // 只删除 console.log
drop_debugger: true, // 删除 debugger
}
}
}
})
删除所有的console语句和debugger,包括console.log、console.warn、console.error等。
import {defineConfig} from "vite";
export default defineConfig({
build: {
minify: 'terser', // 启用 terser 压缩
terserOptions: {
compress: {
drop_console: true, // 删除所有 console
drop_debugger: true,// 删除 debugger
}
}
}
})
文件压缩
npm i vite-plugin-compression -D
pnpm add vite-plugin-compression -D
// build.rollupOptions.plugins[]
viteCompression({
verbose: true, // 是否在控制台中输出压缩结果
disable: false,
threshold: 10240, // 如果体积大于阈值,将被压缩,单位为b,体积过小时请不要压缩,以免适得其反
algorithm: 'gzip', // 压缩算法,可选['gzip',' brotliccompress ','deflate ','deflateRaw']
ext: '.gz',
deleteOriginFile: true // 源文件压缩后是否删除(我为了看压缩后的效果,先选择了true)
})
当请求静态资源时,服务端发现请求资源为gzip的格式时,应该设置响应头 content-encoding: gzip 。因为浏览器解压也需要时间,所以代码体积不是很大的话不建议使用 gzip 压缩。
图片资源压缩:
安装插件
npm i vite-plugin-imagemin -D
pnpm add vite-plugin-imagemin -D
在vite.config.js里面配置
import viteImagemin from 'vite-plugin-imagemin'
plugin: [
viteImagemin({
gifsicle: {
optimizationLevel: 7,
interlaced: false
},
optipng: {
optimizationLevel: 7
},
mozjpeg: {
quality: 20
},
pngquant: {
quality: [0.8, 0.9],
speed: 4
},
svgo: {
plugins: [
{
name: 'removeViewBox'
},
{
name: 'removeEmptyAttrs',
active: false
}
]
}
})
]
压缩前的图片资源大小:
压缩后的图片资源,整体瘦身60%以上
CDN 加速
插件安装:
pnpm add rollup-plugin-external-globals -D
pnpm add vite-plugin-html -D
<head>
<%- injectScript %>
</head>
vite.config.js中配置
import { createHtmlPlugin } from 'vite-plugin-html'
rollupOptions: {
// 告诉打包工具 在external配置的 都是外部依赖项 不需要打包
external: ['vue'],
plugins: [
externalGlobals({
// "在项目中引入的变量名称":"CDN包导出的名称,一般在CDN包中都是可见的"
vue: 'Vue'
})
]
}
plugins: [
createHtmlPlugin({
minify: true,
inject: {
data: {
injectScript: '<script src="https://cdn.jsdelivr.net/npm/vue@3.2.37"></script>'
}
}
})
]
采用CDN引入的弊端:
- 可靠性:使用CDN引入外部模块意味着依赖于第三方服务商的可用性和稳定性。如果CDN服务商发生故障或者网络问题,可能会导致外部模块无法加载,影响网站的正常运行。
- 安全性:使用CDN引入外部模块需要信任第三方服务商,因为模块实际上是从服务商的服务器上加载的。如果服务商被黑客攻击或者恶意篡改了模块的内容,可能会导致安全问题。
- 性能:CDN服务通常会根据用户的地理位置选择最近的节点进行内容分发,这样可以减少网络延迟和提高访问速度。但是如果用户所在地区的CDN节点发生故障或者网络拥堵,可能会导致加载速度变慢甚至加载失败。
- 版本控制:使用CDN引入外部模块可能会导致版本控制的问题。如果模块的版本发生变化,CDN服务商可能会立即更新节点上的内容,这样可能会导致网站出现兼容性问题或者功能异常。
按需加载优化一些包的体积
比如loadsh,项目中只用到了{cloneDeep 、throttle、debouce}这个几个函数,但是由于lodash是common.js版本不支持按需引入,500多k全部打包进来了。
lodash-es 是 lodash 的 es modules 版本 ,是着具备 ES6 模块化的版本,支持按需导入,使用loadsh-es代替lodash,按需引入,减少打包体积。
import _ from 'lodash-es'; // 你将会把整个lodash的库引入到项目
import { cloneDeep } from 'lodash-es'; // 你将会把引入cloneDeep引入到项目
CDN加速
打包构建时,不打包配置指定的外部模块,减少应用打包出来的包体积,使用CDN方式来引用(不建议使用第三方cdn,原因见下文分析,这里做学习讨论使用)
插件安装
pnpm add rollup-plugin-external-globals -D
vite.config.ts里面配置
import externalGlobals from 'rollup-plugin-external-globals';
const globals = externalGlobals({
moment: 'moment',
'video.js': 'videojs',
jspdf: 'jspdf',
xlsx: 'XLSX',
});
export default defineConfig({
build: {
rollupOptions: {
external: ['moment', 'video.js', 'jspdf','xlsx'],
plugins: [globals],
}
}
});
同时需要在 index.html 模版中引入对应库的CDN。
具体的CDN链接请根据自己的需要去官网或是CDN网站查询 , cdn网站 : cdnjs.com/
https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js
https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js
https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js
<script src="https://.../moment.min.js"></script>
<script src="https://.../xlsx.full.min.js"></script>
<script src="https://.../jspdf.polyfills.umd.js"></script>
<script src="https://.../jspdf.umd.min.js"></script>
<script src="https://.../video.min.js"></script>
优化效果,4.14M->2.85M
采用CDN引入的弊端:
- 可靠性:使用CDN引入外部模块意味着依赖于第三方服务商的可用性和稳定性。如果CDN服务商发生故障或者网络问题,可能会导致外部模块无法加载,影响网站的正常运行。
- 安全性:使用CDN引入外部模块需要信任第三方服务商,因为模块实际上是从服务商的服务器上加载的。如果服务商被黑客攻击或者恶意篡改了模块的内容,可能会导致安全问题。
- 性能:CDN服务通常会根据用户的地理位置选择最近的节点进行内容分发,这样可以减少网络延迟和提高访问速度。但是如果用户所在地区的CDN节点发生故障或者网络拥堵,可能会导致加载速度变慢甚至加载失败。
- 版本控制:使用CDN引入外部模块可能会导致版本控制的问题。如果模块的版本发生变化,CDN服务商可能会立即更新节点上的内容,这样可能会导致网站出现兼容性问题或者功能异常。
图片懒加载
使用vite-plugin-vue-lazyload插件来实现图片懒加载功能
npm install vite-plugin-vue-lazyload
pnpm add vite-plugin-vue-lazyload
在项目的vite.config.js文件中引入vite-plugin-vue-lazyload并进行配置:
import vue from '@vitejs/plugin-vue'
import VueLazyload from 'vite-plugin-vue-lazyload'
export default {
// ...其他配置
plugins: [
vue(),
VueLazyload({
// 配置选项
loading: 'loading.gif', // 默认加载中的占位图
error: 'error.gif', // 默认加载错误的占位图
}),
],
};
vite-plugin-vue-lazyload插件的配置选项与vue-lazyload库的配置选项相同,根据需要进行配置,例如指定加载中和加载错误时的占位图等。
具体组件的使用:
Vue组件中使用v-lazy指令来实现图片懒加载功能
<template>
<img v-lazy="'image.jpg'" alt="My Image">
</template>
题外话:SEO优化,vite实现预渲染
yarn add vite-plugin-prerender -D
npm i vite-plugin-prerender -D
pnpm add vite-plugin-prerender -D
在vite.config.js中使用
import vitePrerender from 'vite-plugin-prerender'
import path from 'path'
export default () => {
return {
plugins: [
vitePrerender({
// Required - The path to the vite-outputted app to prerender.
staticDir: path.join(__dirname, 'dist'),
// Required - Routes to render.
routes: ['/', '/chat', '/design'],
}),
],
}
}
打包完成后,会根据配置的路由地址,在dist文件中生成对应的html文件。
sequenceDiagram
Alice->>John: Hello John, how are you?
John-->>Alice: Great!
Alice-)John: See you later!