vite3+vue3 项目打包优化实战之-视图分析(rollup-plugin-visualizer)CDN引入依赖分包gzip压缩history404问题
Posted Min.Mr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vite3+vue3 项目打包优化实战之-视图分析(rollup-plugin-visualizer)CDN引入依赖分包gzip压缩history404问题相关的知识,希望对你有一定的参考价值。
文章目录
写在前面
vue项目在线下环境开发完成后,我们就需要项目的打包上线了,除了要知道打包命令npm run build
之外,我们还要知道项目整体文件依赖情况,web访问加载速度等概念,包括首屏优化方案。我通过一次实战把最基本可以优化的步骤走一下。
将分为以下几个步骤:
- build 视图分析依赖文件
- 第三方库CDN引入
- 依赖文件分包
- gzip压缩文件
- 部署前配置history路由模式的404问题
build 视图分析依赖文件
分析项目中的文件大小及引用情况,是优化前的重要一步,从而去采取文件分包,cdn引入等相关技术概念,那么在vite下我们可以利用什么工具来做项目的依赖分析呢?
答案是:
Rollup Plugin Visualizer
,这是一个依赖分析插件,它提供了多种模式的依赖分析,包括直观的视图分析,sunburst(循环层次图,像光谱)、treemap(矩形层次图,看起来比较直观,也是默认参数)、network(网格图,查看包含关系)、raw-data(原数据模式,json格式), list(列表模式),你可以选择任意一种你喜欢的观察模式,这里我们就以默认的为例;
安装方式如下:
npm install --save-dev rollup-plugin-visualizer
yarn add --dev rollup-plugin-visualizer
❗选择一种安装即可;
安装完成后,即可在vite下的插件属性中进行配置:
import visualizer from 'rollup-plugin-visualizer';
export default defineConfig(
plugins: [vue(), visualizer(
emitFile: false,
file: "stats.html", //分析图生成的文件名
open:true //如果存在本地服务端口,将在打包后自动展示
)],
)
配置的参数有很多是默认的,如果你没有特殊需求,完全可以不添加参数;下面我添加一个表格对已有参数进行诠释:
参数 | 类型 | 解释 |
---|---|---|
filename/file | string | 生成分析的文件名 |
title | string | html标签页标题 |
open | boolean | 以默认服务器代理打开文件 |
template | string | 可选择的图表类型 |
gzipSize | boolean | 搜集gzip压缩包的大小到图表 |
BrotliSize | boolearn | 搜集brotli压缩包的大小到图表 |
emitFile | boolean | 使用emitFile生成文件,简单说,这个属性为true,打包后的分析文件会出现在打包好的文件包下,否则就会在项目目录下 |
sourcemap | boolean | 使用sourcemap计算大小 |
projectRoot | string, RegExp | 文件的根目录,默认在打包好的目录下 |
看完这些参数,也有了大概的了解,根据需求配置就好
接下来,你只需要npm run build
;就可以查看这个图表了
是不是很好看,五颜六色的,这里颜色也是有说法的:
🟦蓝色表示自己写下的js文件项;
🟩绿色是表示依赖的文件项;
其他颜色我们可以根据文件名来判断
像上面这个文件,明显我们可以看出这是router相关的文件,当鼠标点击时我们可以看出这块依赖文件的大小,他的位置是是哪里;这里也看到它的大小马上到了100kb,是因为我们的主要业务也确实在这里;那我们就可以通过这样的信息采取一些优化方案,包括不限于修改代码的设计方式等,那么下面要说的CDN引入就是为了减少如element-plus及bootstrap5的打包文件大小,减少本地文件载入压力。下图很直观的可以看出element-plus的占据程度
第三方库CDN引入
🤔CDN 是构建在数据网络上的一种分布式的内容分发网。 CDN
的作用是采用流媒体服务器集群技术,克服单机系统输出带宽及并发能力不足的缺点,可极大提升系统支持的并发流数目,减少或避免单点失效带来的不良影响。
上面是百度百科的一段话,这里我要cdn引入是因为我们只有一个服务器,便称为单系统;那么引入他们各自官方的cdn链接就是在利用分布式内容分发技术,但是毕竟是人家的cdn安全上还需要考虑,如果自己公司有条件,就可以用自己公司的保证安全性;
话接上文,我们通过视图分析发现了element-plus
是最大的文件依赖,包括
bootstrap5
,那我们就尝试在vite+vue下配置这俩个库的cdn引入来减少请求压力;
cdn管理插件我们使用vite-plugin-cdn-import
安装方式
npm install vite-plugin-cdn-import --save-dev
yarn add vite-plugin-cdn-import -D
选择自己的包管理器下载
// vite.config.js 基本用法
import reactRefresh from '@vitejs/plugin-react-refresh'
import importToCDN from 'vite-plugin-cdn-import'
export default
plugins: [
importToCDN(
modules: [
name: 'react',
var: 'React',
path: `umd/react.production.min.js`,
,
name: 'react-dom',
var: 'ReactDOM',
path: `umd/react-dom.production.min.js`,
,
],
),
],
有一些model该插件还提供了自动完成,不要太爽,我们不需要配置参数了
export default
plugins: [
importToCDN(
modules: [
autoComplete('react'),
autoComplete('react-dom')
],
),
reactRefresh(),
],
写法如上,那么有那些是支持自动完成的呢,官方也写出了
自动完成支持的 module
“react” | “react-dom” | “react-router-dom” |
“antd” | “ahooks” | “@ant-design/charts” |
“vue” | “vue2” | “@vueuse/shared” |
“@vueuse/core” | “moment” |
“eventemitter3” | “file-saver” |
“browser-md5-file” | "xlsx | “crypto-js” |
“axios” | “lodash” | “localforage”
接下来我们再看完参数配置即可完成cdn的相关配置
这里的相关属性配置你们去官方看吧,很明确vite-plugin-cdn-import
然后还需要知道是常见cdn网站,我们主要介绍俩个国外的,也是常用的,
UNPKG:https://unpkg.com
jsDelivr :https://www.jsdelivr.com
这里还要学习怎么找到对应库cdn包的路径,我们好来配置参数,以UNPKG
为例实践如下:
比如我们要配置element-plus的cdn引入,
- 先进入https://unpkg.com
- 在地址后面链接你的包名
- 得到链接配置参数即可
下面我附图来展示:
package.json找到你的包信息
浏览器拼接你的包并且回车:
你会发现页面请求到了内容(这就说明该库在cdn上已经存在,我们把整个的链接拿下来配置好参数就可以了):
到这里你已经掌握了cdn库自动构建的基本知识,下面看一下我的配置片段:
import defineConfig from 'vite'
import vue from '@vitejs/plugin-vue'
import autoComplete, Plugin as importToCDN from 'vite-plugin-cdn-import';
export default defineConfig(
plugins: [vue(),
importToCDN(
prodUrl: 'https://unpkg.com/name@version/path',
modules: [
autoComplete('vue'),
autoComplete('axios'),
name: 'element-plus',
var: 'ElementPlus', //根据main.js中定义的来
version: '2.2.17',
path: 'dist/index.full.js',
css: 'dist/index.css'
,
name: 'vue-demi',
var: 'VueDemi', //根据main.js中定义的来
version: '0.13.11',
path: 'lib/index.iife.js'
,
name: '@element-plus/icons-vue',
var: 'ElementPlusIconsVue', //根据main.js中定义的来
version: '2.0.9',
path: 'dist/index.iife.min.js'
,
name: 'bootstrap',
var: 'bootStrap', //根据main.js中定义的来
version: '5.2.1',
path: 'dist/js/bootstrap.js',
css: 'dist/css/bootstrap.min.css'
,
],
)
],
)
上面的配置中有一个问题需要提及,我配置了
vue-demi
,它是pinia仓库的依赖,简单说,如果不配置它我们的cdn构建中间出现了个缺口,它是pinia-vue中间的一个依赖;vue和axios我配置了自动完成,那接下来看下我们进入实战。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="./static/ico/favicon-a91524b8.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>xxxxx</title>
<script type="module" crossorigin src="./static/js/index-3f77d0fe.js"></script>
<link rel="modulepreload" crossorigin href="./static/js/@vue-57a1150c.js">
<link rel="modulepreload" crossorigin href="./static/js/js-cookie-1db5286e.js">
<link rel="modulepreload" crossorigin href="./static/js/axios-08851a62.js">
<link rel="modulepreload" crossorigin href="./static/js/lodash-es-9a8f223b.js">
<link rel="modulepreload" crossorigin href="./static/js/@vueuse-d210d573.js">
<link rel="modulepreload" crossorigin href="./static/js/@element-plus-1fa478d9.js">
<link rel="modulepreload" crossorigin href="./static/js/@popperjs-892fd7f5.js">
<link rel="modulepreload" crossorigin href="./static/js/@ctrl-eb0b847c.js">
<link rel="modulepreload" crossorigin href="./static/js/dayjs-54e8cf14.js">
<link rel="modulepreload" crossorigin href="./static/js/async-validator-efc2d198.js">
<link rel="modulepreload" crossorigin href="./static/js/memoize-one-99e54574.js">
<link rel="modulepreload" crossorigin href="./static/js/escape-html-4bbaf1e1.js">
<link rel="modulepreload" crossorigin href="./static/js/normalize-wheel-es-da779ce4.js">
<link rel="modulepreload" crossorigin href="./static/js/@floating-ui-4b8fd220.js">
<link rel="modulepreload" crossorigin href="./static/js/element-plus-88e408ab.js">
<link rel="modulepreload" crossorigin href="./static/js/vue-router-5a9da933.js">
<link rel="modulepreload" crossorigin href="./static/js/vue-demi-5b9a0fa5.js">
<link rel="modulepreload" crossorigin href="./static/js/pinia-ef1d9feb.js">
<link rel="modulepreload" crossorigin href="./static/js/@fortawesome-7be7f9bf.js">
<link rel="stylesheet" href="./static/css/element-plus-c08499e6.css">
<link rel="stylesheet" href="./static/css/index-f2f66543.css">
<link rel="stylesheet" href="./static/css/bootstrap-744009a1.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
这样的入口文件,这么多的link是我提前用了分包的效果,下面我们会实战分包;回到上面,这么多的link引入对我们本地的压力可想而知;再来看分析图:
element-plus的依赖是如此庞大,那我们配置完后,build再来感受下;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="./static/ico/favicon-a91524b8.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>xxxxxxxxx</title>
<link href="https://unpkg.com/element-plus@2.2.17/dist/index.css" rel="stylesheet">
<link href="https://unpkg.com/bootstrap@5.2.1/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://unpkg.com/vue@3.2.36/dist/vue.global.prod.js"></script>
<script src="https://unpkg.com/axios@0.27.2/dist/axios.min.js"></script>
<script src="https://unpkg.com/element-plus@2.2.17/dist/index.full.js"></script>
<script src="https://unpkg.com/vue-demi@0.13.11/lib/index.iife.js"></script>
<script src="https://unpkg.com/@element-plus/icons-vue@2.0.9/dist/index.iife.min.js"></script>
<script src="https://unpkg.com/bootstrap@5.2.1/dist/js/bootstrap.js"></script>
<script type="module" crossorigin src="./static/js/index-8dbc54cb.js"></script>
<link rel="modulepreload" crossorigin href="./static/js/js-cookie-1db5286e.js">
<link rel="modulepreload" crossorigin href="./static/js/vue-router-5755d64e.js">
<link rel="modulepreload" crossorigin href="./static/js/pinia-7992cf6b.js">
<link rel="modulepreload" crossorigin href="./static/js/@fortawesome-0742f1fb.js">
<link rel="stylesheet" href="./static/css/index-f2f66543.css">
<link rel="stylesheet" href="./static/css/element-plus-c08499e6.css">
<link rel="stylesheet" href="./static/css/bootstrap-744009a1.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
cdn标签引入正确,我们也可以本地构建serve 来验证效果,这里就不扩展了,那么再看下分析图
element-plus等第三方库将不会成为我们的本地依赖,这里的tool是我自己的js工具模块,他看起来也是很大,那我们就可以找方法去优化调整,至此你学会了vite框架下的vue项目cdn引入方式;
还有一点题外话,cdn引入之前:
- 你需要知道一但依赖网站出现问题,我们的项目也就不行了,所以有依赖如上网站的cdn建议留下备用方案,以便维护。
- cdn是对整个库的引入,在你引入前,你要对一个库足够熟悉,比如我有一个
好朋友
他就在cdn引入中上出现了问题;
大致是这样:项目是vue3项目,我们知道在vue3中的reactive
响应式对象函数,
//它可以这样导入:
import reactive from "@vue/reactivity";
//也可以这样:
import onBeforeMount, ref, reactive from "vue";
那么如果你用@vue/reactivity
来导入,上线后发现reactive响应式没了,别问我怎么知道的,我朋友说的。我们cdn可没有引入该组件的相关依赖,只是在本地\\node_modules
下才有;
依赖文件分包
🤔在我们没有配置构建工具的分包功能时,构建出来的build将无比巨大且是独立的一个js and css 文件,这样就会存在本地加载文件的压力,已经成熟的方案在rollup 和 webpack中都有概念;
在vite的官方介绍中有这么一段
build.rollupOptions¶
类型: RollupOptions
自定义底层的 Rollup 打包配置。这与从 Rollup 配置文件导出的选项相同,并将与 Vite 的内部 Rollup 选项合并。查看 Rollup 选项文档 获取更多细节。
vite底层已经集成了rollup的一部分功能,也就是说我们直接配置好即可;详细关于rollup的配置可以去看官方文档rollupjs;这里我直接给出我的配置情况,也是借鉴部分大佬的文章得出;
export default defineConfig(
plugins: [vue(), viteCompression(
verbose: true,
disable: false,
threshold: 10240,
algorithm: 'gzip',
ext: '.gz',
),
importToCDN(
prodUrl: 'https://unpkg.com/name@version/path',
modules: [
autoComplete('vue'),
autoComplete('axios'),
name: 'element-plus',
var: 'ElementPlus', //根据main.js中定义的来
version: '2.2.17',
path: 'dist/index.full.js',
css: 'dist/index.css'
,
vue项目打包上线
一.项目打包
-
首先在打包之前做两个优化操作
-
优化一:在vite.congfig(vite.config.ts文件)去掉项目中console.log和debugger
解决方式:在vite.config.ts文件中添加esbuild:drop:["console","debugger"]
export default defineConfig(
esbuild:
drop:['console','debugger']//打包时去掉console语句
,
plugins: [vue(), vueJsx()],
resolve:
alias:
'@': fileURLToPath(new URL('./src', import.meta.url)),
'#': fileURLToPath(new URL('./types', import.meta.url))
,
server:
proxy:
"/m.api":
target: 'http://192.168.1.188:8080',
changeOrigin: true
,
"/upload/admin": //图片上传地址
target: 'http://192.168.1.188:8080', // 后端服务实际地址
changeOrigin: true,
ws: true
)
-
优化二:在package.json(package.json文件)去掉ts类型检查
解决方式:"build": "run-p type-check build-only"改为"build": "run-p build-only"
2.打包
npm run build
3.预览打包后的项目
npm run preview
4.预览时遇到的一些问题
-
问题1:echarts首次渲染没问题,第二次渲染却成空白
- 产生原因:echarts插件自带的bug
- 解决方式:
onBeforeUnmount(() => //防止echarts带来的空白bug
if (column)
column.dispose()
column = undefined
if (line)
line.dispose()
line = undefined
if (pie)
pie.dispose()
pie = undefined
if (pies)
pies.dispose()
pies = undefined
)
-
问题2:图标出现错误,控制台输出404
-
产生原因:未找到图标文件,路径错误
-
解决方法:在入口index.html文件中路径中的"."去掉
<link rel="icon" href="./favicon.ico">
改为
<link rel="icon" href="/favicon.ico">
<link rel="stylesheet" href="./public/iconfont/iconfont.css">
改为
<link rel="stylesheet" href="/public/iconfont/iconfont.css">
二、项目上线
使用宝塔第三方工具来上线,首先进入公司宝塔的网址,然后输入账户和密码进入宝塔主页,然后创建一个网站,创建网站之后把打包好的dist文件上传到网站目录中
1.首先进入宝塔首页宝塔Linux面板(宝塔Linux面板)
2.进入创建好的网站
3.点击选择添加站点
4.填写公司给的域名,然后点击提交
5.跳转到创建好之后的页面,单击刚刚创建好的域名
6.站点创建好之后可以访问创建好的站点
7.表示此站点创建成功
8.然后把打包好的dist文件夹,上传
9.单击上传
10.正在上传
11.打开dist文件
12.复制dist文件夹中所有的文件
13.然后我们在返回dist文件夹,单击粘贴,选择确定
14.上线的整体文件夹
15.注意:
-
问题:上线之后页面会报一个404错误
-
解决1:将路由模式改为hash模式,在router文件夹下的index.ts
history: createWebHistory(import.meta.env.BASE_URL)
改为
history: createWebHashHistory(import.meta.env.BASE_URL)
-
解决2:不改变路由模式,修改服务器配置文件
回到宝塔,找到配置文件,点击设置设置反代理
这里以nginx类型的服务器为例, 在宝塔中站点设置中配置文件里"禁止访问的文件或目录"的位置添加一下代码,据vue-router官方文档去添加nginx配置(添加一个简单的回退路由)
16.打包上线成功之后页面
以上是关于vite3+vue3 项目打包优化实战之-视图分析(rollup-plugin-visualizer)CDN引入依赖分包gzip压缩history404问题的主要内容,如果未能解决你的问题,请参考以下文章