最近参与一个使用Nuxt+element-ui构建的Vue项目,由于要做SEO所以部分页面采用ssr(server side render)

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

优化第一步,首先使用Nuxt自带集成的webpackbundle-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

加载性能

51 个评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注