最近参与一个使用Nuxt+element-ui构建的Vue项目,由于要做SEO所以部分页面采用ssr(server side render)
这个项目本身最重要的就是首页展示,但是由于部分业务逻辑涉及到表单再加上布局方便,所以引入了ElementUI,这导致了整个项目异常臃肿,再加上ElementUi自带的slider组件不支持移动端的滑动,所以我又引入了第三方轮播组件Swiper,这两个库占用了大量的空间,导致最后打包出来的vendor.app.js+app.js有5-6MB,大大降低了首页首次加载速度,用户体验很糟糕

优化第一步,首先使用Nuxt自带集成的webpack–bundle-analyzer 查看打包后的文件占用情况

ElementUI占用1.5mb,另外还不包括自带的Scss样式文件,所以这里用到官方文档提供的按需加载
以前注入ElementUI很暴力,直接引用

这样导致所有的组件,即使没有用过的也会加载,按照官方的文档,可使用babel-plugin-component来实现按需加载
npm install babel-plugin-component -D
并在.babelrc中配置 (Nuxt是在nuxt.config.js)
"plugins": [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ] ]
import Vue from 'vue'; import { Button, Select } from 'element-ui'; import App from './App.vue'; Vue.component(Button.name, Button);
这个插件主要就是通过babel来实现只引用需要的组件,除此之外还可以不用该插件,自己手动引用组件

需要注意的是,如果不使用babel-plugin-component,那么在项目中每一个引入element的地方都要引用精确路径,不然最后打包还是会把整个ElementUI打进去

这样确实可行,也降低了打包后的文件大小,但是这只是减小了js文件的占用,同理,scss样式也可以按需引入才对

修改为只引用用到过的组件样式

在处理Swiper的时候,我发现在Vue中其实可以不用使用组件注册的方式来引用Swiper,所以我改用引用min.js直接实例化来使用Swiper
以上是在引用、打包层面降低代码占用大小,下面说说代码层面,比较关键的就是懒加载技术
可以通过路由懒加载,组件懒加载,来看降低首次加载页面的文件大小
webpack在打包时会将凡是用到东西关联起来,合成一个文件,那么举个栗子,如果所有路由一来,不管用没有用,先放在那,比如
import xxx1 from "@/xxx/xxx"; import xxx2 from "@/xxx/xxx" const router = new Router([ { name: "name1", url: "url1", component: "xxx1" }, { name: "name2", url: "url2", component: "xxx2" } ])
那么编译后必然把所有页面都引用在一起,那么加载首页,其实也把什么用户、登陆、等等其他页面的文件资源都加载了,其实没有必要
修改后的路由应该是这样的
const router = new Router([ { name: "name1", url: "url1", component: ()=>import("@/xxx/xxx") }, { name: "name2", url: "url2", component: resolve => { require(["@/xxx/xxx/xxx"], resolve); }, } ])
组件同理,在需要用到的时候再去加载,这样修改后,打包的目录结构会发生变化,首页资源一定会减小不少
当然,前端的加载优化当然离不开gzip这个神器,不过我还没有深入了解,大致配置了一下参数,能用就行,有空钻研!
最后看一下优化后的资源情况

ElementUI : 1.5 MB -> 0.6 MB
Swiper: 230 KB -> 120 KB
scss: 220 KB -> 120 KB
加载性能

Tasarım Firması İçin Tıkla. Tasarım Firması Bul.