vue 第三方组件按需引入,最后项目的包体积真的变小了吗?

您所在的位置:网站首页 压缩文件体积不变 vue 第三方组件按需引入,最后项目的包体积真的变小了吗?

vue 第三方组件按需引入,最后项目的包体积真的变小了吗?

2024-03-22 23:22| 来源: 网络整理| 查看: 265

一、一个困扰前端的问题

前端打包体积的优化,减少打包体积,也算是前端老生常谈的问题了。 我们最常用的方法之一就是按需引入组件! 各大组件库,如ant-design,element-ui,都有按需引入的栗子,有些会告诉你,按需引入,可以减少包体积!

百度搜索“组件按需引入”,会有一大堆文章告诉你组件如何按需引入,并且大部分都不约而同的复制了这句话:按需引入可以减少打包体积!

事实果真如此?

No! 二、不信任起源

对于这事,开始时鄙人也深信不疑。项目开发里面,能按需引入的都选择按需引入了,毕竟优化的意识深深刻在脑海里。

最近在写组件库,却让我对这个问题产生了怀疑。

本来嘛,因为历史原因,还有为了项目进度原因,我们的组件库开始是写在项目里面的,只是把他大概按照组件库的模式,单独存放于文件夹里面,后来有空了,就把之前备用好的组件抽了出来,组成公司组件库。一切搞好后,替换了之前项目里面的内置组件。然后打包,当我把打包好的zip文件发给后端小伙伴的时候,赫然发现,使用了组件库后的项目,包体积比之前增加了约1.5M!!

瞬间就感觉不能接受了!为什么会这样?这不是我想要的结果!

但是,因为组件库要在后面的新项目推广使用,抽出来是必需!那就着手优化解决呗!

开始写组件库,打包为了方便快捷,并没有自己去构建打包方式,直接用的vue的库模式打包,打出来的包是全部打成一块的。所以一开始的优化思路就是,做成可以按需引入的打包方式。怎么做?找个参考的吧,虽然我们的库是基于ant-design-vue的,但是参考的还是选择了element-ui,没有别的,就是element-ui的代码看着比ant-design-vue顺眼,可阅读性也较好。element-ui库打包后的文件是这样的,把每个组件单独打包成一个js文件 在这里插入图片描述

经过一番折腾,终于搞好了可以像这样的按需引入

import Button from "element-ui/lib/button"

这个时候兴高采烈的对着项目就是一顿改,一顿操作猛如虎,结果发现,这nm优化了个寂寞,因为使用按需引入后,打包后的代码体积比没有使用按需引入的还要多出1M 在这里插入图片描述

三、根源所在

受挫后,又重新换了一种方式打包,结果相差无几!

然后冷静下来,对这种按需打包模式打包后的文件进行分析。首先选中所有按组件单独打包得到的js文件,看了一下总体积,确实比统一打包要大1M多。

为什么?

想了一下其实也很好理解。我们封装组件库的时候,总有公用的函数吧?有公用的组件吧?有公用的依赖吧?这些公用的东西,如果我们统一打包,那么他们就只有一份,每个组件都去引用就好了。

但是,如果我们要将一个单独的组件打包成一个可以独立用的js模块,那他就不得不把这些公共的东西包进去。这下子好了,假设我有A、B、C三个组件,共同依赖了D模块,A、B、C分别为10kb大小,D是5kb大小,统一打包的情况下,总共就35kb,分开打包呢?A、B、C都会变成15kb,三个就成了45kb了。

体积就是这么被增大的!!

验证

为了验证这想法,我们新建一个size-test项目来看看

在这里插入图片描述

这里按鄙人的项目习惯,建了一个vue2+less+vuex+router的项目,然后我们先安装ant-design-vue

npm i [email protected] --save

然后在main.js全局引入ant-design-vue

import Vue from "vue" import antd from "ant-design-vue" Vue.use(antd)

然后执行打包命令,npm run build 打包后,将dist压缩为zip 在这里插入图片描述 如上图,此时的包体积压缩后是2.05M

接下来我们把项目改成按需引入的形式,将main.js改成如下

import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' // import antd from "ant-design-vue" Vue.config.productionTip = false // Vue.use(antd) import Affix from 'ant-design-vue/lib/affix'; import Anchor from 'ant-design-vue/lib/anchor'; import AutoComplete from 'ant-design-vue/lib/auto-complete'; import Alert from 'ant-design-vue/lib/alert'; import Avatar from 'ant-design-vue/lib/avatar'; import BackTop from 'ant-design-vue/lib/back-top'; import Badge from 'ant-design-vue/lib/badge'; import Base from 'ant-design-vue/lib/base'; import Breadcrumb from 'ant-design-vue/lib/breadcrumb'; import Button from 'ant-design-vue/lib/button'; import Calendar from 'ant-design-vue/lib/calendar'; import Card from 'ant-design-vue/lib/card'; import Collapse from 'ant-design-vue/lib/collapse'; import Carousel from 'ant-design-vue/lib/carousel'; import Cascader from 'ant-design-vue/lib/cascader'; import Checkbox from 'ant-design-vue/lib/checkbox'; import Col from 'ant-design-vue/lib/col'; import DatePicker from 'ant-design-vue/lib/date-picker'; import Divider from 'ant-design-vue/lib/divider'; import Dropdown from 'ant-design-vue/lib/dropdown'; import Form from 'ant-design-vue/lib/form'; import FormModel from 'ant-design-vue/lib/form-model'; import Icon from 'ant-design-vue/lib/icon'; import Input from 'ant-design-vue/lib/input'; import InputNumber from 'ant-design-vue/lib/input-number'; import Layout from 'ant-design-vue/lib/layout'; import List from 'ant-design-vue/lib/list'; import LocaleProvider from 'ant-design-vue/lib/locale-provider'; import Menu from 'ant-design-vue/lib/menu'; import Mentions from 'ant-design-vue/lib/mentions'; import Modal from 'ant-design-vue/lib/modal'; import Pagination from 'ant-design-vue/lib/pagination'; import Popconfirm from 'ant-design-vue/lib/popconfirm'; import Popover from 'ant-design-vue/lib/popover'; import Progress from 'ant-design-vue/lib/progress'; import Radio from 'ant-design-vue/lib/radio'; import Rate from 'ant-design-vue/lib/rate'; import Row from 'ant-design-vue/lib/row'; import Select from 'ant-design-vue/lib/select'; import Slider from 'ant-design-vue/lib/slider'; import Spin from 'ant-design-vue/lib/spin'; import Statistic from 'ant-design-vue/lib/statistic'; import Steps from 'ant-design-vue/lib/steps'; import Switch from 'ant-design-vue/lib/switch'; import Table from 'ant-design-vue/lib/table'; import Transfer from 'ant-design-vue/lib/transfer'; import Tree from 'ant-design-vue/lib/tree'; import TreeSelect from 'ant-design-vue/lib/tree-select'; import Tabs from 'ant-design-vue/lib/tabs'; import Tag from 'ant-design-vue/lib/tag'; import TimePicker from 'ant-design-vue/lib/time-picker'; import Timeline from 'ant-design-vue/lib/timeline'; import Tooltip from 'ant-design-vue/lib/tooltip'; import Upload from 'ant-design-vue/lib/upload'; import Drawer from 'ant-design-vue/lib/drawer'; import Skeleton from 'ant-design-vue/lib/skeleton'; import Comment from 'ant-design-vue/lib/comment'; import ConfigProvider from 'ant-design-vue/lib/config-provider'; import Empty from 'ant-design-vue/lib/empty'; import Result from 'ant-design-vue/lib/result'; import Descriptions from 'ant-design-vue/lib/descriptions'; import PageHeader from 'ant-design-vue/lib/page-header'; import Space from 'ant-design-vue/lib/space'; const components = [ Base, Affix, Anchor, AutoComplete, Alert, Avatar, BackTop, Badge, Breadcrumb, Button, Calendar, Card, Collapse, Carousel, Cascader, Checkbox, Col, DatePicker, Divider, Dropdown, Form, FormModel, Icon, Input, InputNumber, Layout, List, LocaleProvider, Menu, Mentions, Modal, Pagination, Popconfirm, Popover, Progress, Radio, Rate, Row, Select, Slider, Spin, Statistic, Steps, Switch, Table, Transfer, Tree, TreeSelect, Tabs, Tag, TimePicker, Timeline, Tooltip, Upload, Drawer, Skeleton, Comment, // ColorPicker, ConfigProvider, Empty, Result, Descriptions, PageHeader, Space, ] components.forEach(item => { Vue.use(item) }) new Vue({ router, store, render: h => h(App) }).$mount('#app')

然后npm run build,打包看看结果,如下图 在这里插入图片描述 可以看得出来,比全局引入要多100kb,而且这里,你如果仔细去数的话,发现按需引入的,我还漏掉了个别组件,所以实际应该比这个还要大点点。

但是,这个差别也不大嘛。比起实际项目中的情况,虽说是要大点,但是没大多少。

别急,我们再来改下,将app.vue修改如下:

Home | About #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } nav { padding: 30px; a { font-weight: bold; color: #2c3e50; &.router-link-exact-active { color: #42b983; } } }

这时候在项目中假设我们引用了组件,然后main.js还是先改成全局引入,打包,结果如下:

在这里插入图片描述 我们可以看到,app.vue引入组件后,打包没太多变化。 然后我们改成按需引入,再打包 在这里插入图片描述 结果很明显,按需打包后,立马增加了10kb!!

那么在复杂的项目中,组件的大量使用,会不会增加的更多?答案是肯定的!鄙人的项目里面,按需和全局引入,按需引入要多出300kb,这是在按需引入时至少有十个组件没有引入的情况下。

接下来我们按照刚才的思路,看看element-ui的情况 在这里插入图片描述

这是element-ui的测试结果,dist.zip为全局引入没有使用标签,dist(2).zip是按需引入没有使用标签,dist(3)是全局引入且使用 了标签,dist(4)是按需引入且使用了标签

我的天,虽然趋势没有变,就是总体上按需引入的包会更大,但是element-ui和ant-design-vue有1M左右的差距。从这里也许也能看出一些两个组件库的一些优劣(ps:个人更喜欢element-ui,在项目开发中如果使用了table组件的树形结构渲染,两个组件的性能有很明显区别,element-ui更快哦!!)

然后,我想看看既没有引入ant-design-vue,也没有引入element-ui的情况,如下 在这里插入图片描述 274kb。这也能解释了鄙人的项目里面,为什么将组件抽出去成组件库后,体积会马上增加1.5M的原因,因为组件库是依赖ant-design-vue的,组件库里面塞了ant-design-vue本身的代码啊!!

求助:看到的大佬能教下怎么破嘛?如果组件库只用了js,其实也还好办,组件库可以直接使用项目里面的ant-design-vue,但是组件库用了ts以后,项目注册的ant-design-vue没法使用了,会报找不到标签的错误!所以不得不在库里面单独引入ant-design-vue,这是导致包体积增加1.5M的重要原因

最后,再来试试echarts

echarts全局引入代码

import Vue from "vue" import * as echarts from "echarts" Vue.prototype.$echarts = echarts

echarts按需引入代码

import Vue from "vue" import * as echarts from "echarts/core" import { TitleComponent, ToolboxComponent, TooltipComponent, GridComponent, DataZoomComponent, LegendComponent } from "echarts/components" import { LineChart, PieChart } from "echarts/charts" import { UniversalTransition, LabelLayout } from "echarts/features" import { CanvasRenderer } from "echarts/renderers" echarts.use([ TitleComponent, ToolboxComponent, TooltipComponent, GridComponent, DataZoomComponent, LineChart, CanvasRenderer, UniversalTransition, LegendComponent, PieChart, LabelLayout ]) Vue.prototype.$echarts = echarts

echarts页面渲染的代码太长了,就不贴了,下面是测试结果

在这里插入图片描述

dist.zip为全局引入没有使用标签,dist(2).zip是按需引入没有使用标签,dist(3)是全局引入且使用 了标签,dist(4)是按需引入且使用了标签

这里我们可以看到,按需引入的包体积更小。这也许是和这次测试本身按需引入的echarts组件较少有关,鄙人项目中,echarts按需引入后体积少了1.5M,这个优化还是可以的。至于按需的情况下,如果把所有的echarts组件都引用上会是啥情况,这个就没得去测了,主要是ecahrts页面渲染代码弄起来比较麻烦,不过这几个测试可以说明一点,那就是

想要用按需引入减少包体积,只有在你只用到和全部相比很少组件的情况下有效

如果项目中用了超一半以上的组件,通常全局引入可能会更好,因为可以更好地共用公有部分代码,体积会更小,或者不确定的情况下,都分别使用下,打包看看具体的结果。对于只用了很少组件的第三方库,比如本测试的echarts,按需引入会有很明显的优化效果



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3