前端性能优化(把2M的文件变为75K的过程)

@liushaozhen 2017-07-24 08:19:54发表于 iuap-design/blog

这一周听某产品负责人说的最多的话:“这什么文件?怎么这么大啊!这加载也太慢了!拆啊!异步加载!太慢了太慢了!改一下不就好了嘛!不行不行,还得改,还是太慢!不行就重新做一个啊!宁可重新做也不能这样!。。。”
好,懂的人都知道发生了什么,下边来说一下,前端优化页面加载性能的工具和技巧

背景介绍

项目是用的react写的,webpack打包后将所有的js,css都打包到了一个js中,所以如果页面复杂的时候会很大很大

一、先从代码下手

先看一下 import

import React,{Component} from 'react';
import axios from '../../components/axios'
import {Col,Row,Button,Message  } from 'tinper-bee';
import { DatePicker} from 'antd';
import {loadData,getQueryString,getCookie } from '../../components/util';
import style from './index.css';
import classnames from 'classnames';
import NoData from './NoData';

引入了react,axios,tinper-bee,antd,classnames,index.css,NoData和公用的方法,还有一个组件,react,axios,tinper-bee,classnames,index.css,NoData在不改代码的情况下,这些是不能动的,那么只剩下antd了,嗯,先拿它开刀。翻看了一下官网,使用 import { DatePicker } from 'antd'; 这种方式引入antd的组件会将整个antd打包进来,antd的压缩包 1M多,看看有没有其它办法引入 antd的组件,果然在官网发现了如下方式:

import Button from 'antd/lib/button';
import 'antd/lib/button/style'; // 或者antd/lib/button/style/css 加载 css 文件

官方说明:如果你在开发环境的控制台看到下面的提示,那么你可能使用了 import { Button } from 'antd'; 的写法引入了 antd 下所有的模块,这会影响应用的网络性能。可以通过以上按需加载的方式引入组件。如果你使用了 babel,那么可以使用 babel-plugin-import 来进行按需加载,加入这个插件后。你可以仍然这么写:import { Button } from 'antd';
好,按照官网的方式把 import { DatePicker} from 'antd' 改成了import DatePicker from 'antd/lib/data-picker';import 'antd/lib/datapicker/style/index.css';。然后:66666666666,文件瞬间瘦了1M多,这一波很强势,开局的成功给了我巨大的信息,赶紧继续搞
(注:一些多余代码,多余的引入这里就不说了,效果不是很明显,但是苍蝇也是肉,该删还得删)

二、从webpack打包下手

首先百度一下webpack压缩的技巧,彻底解决 webpack 打包文件体积过大,我从这上边受到了启发。

1.去除不必要的插件

浏览了一下,webpack.config.js配置文件,发现引入的插件都用到了,没有什么多余的插件,所以此方法对我来说无效

2.提取第三方库

前边介绍了,import中引入了react,axios,tinper-bee,然后我看了一下externals如下:

externals: {
       'react': 'React',
       'react-dom': 'ReactDOM',
       'tinper-bee': 'tinper-bee',
       'axios': 'axios',
       'react-router': 'ReactRouter'
  }

我试着把antd提取成第三方,然后产出,测试。然后,失算了,提取成第三方相当于引入了antd的所有的组件,我只用了一个组件,这样就得不偿失了,虽然产出的index.js文件变小了,但是需要加载antd.min.js和antd.min.css文件,导致下载的东西更多,响应时间更久了。此方法无效

3.代码压缩

webpack.config.jsplugins中没有找到UglifyJsPlugin,然后我就加上了这个插件,将js文件压缩,如下图:

plugins: [
        new HappyPack({
            id: 'jsx',
            loaders: ['babel-loader']
        }),
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            }
        })

不错不错,这个使我的文件又缩小了一倍。目前位置文件为500K左右。距离要求,总的加载时间为1.5s左右,还是太慢。
(注:使用UglifyJsPlugin插件之后,在webpack构建的时候,会明显变慢,所以我在测试的时候一般注释掉这一个功能,再正式环境上使用这个功能)

4.代码分割

先来说一下项目的webpack的打包机制:每一个节点都是一个文件夹,所有的css和js打包到一个index.js中,除此之外还有一个index.html。我在移动端的节点要实现,列表,详情,增加的功能。我写代码的时候都是写在一个文件夹下,也就是说打包出来的index.js中包含了列表详情增加的所有功能,只是首页是列表页。我试着把这三个功能拆分开,拆分成三个节点(列表一个,详情一个,增加一个)。这样当用户需要增加或者详情功能的时候,才会去加载对应的文件,而且打包出来是三个index.js,首次给用户展现的只有列表的index.js,这样就会块很多。 产出测试后,目前文件有200K,不错不错,这一步又把文件砍掉了一半多,测试加载时间为500ms-1s之间,哎,还是有点大,看能不能再优化。
其实这一步可以用webpack的按需加载功能,但是项目的框架方面做这个按需加载不是很容易,就没有使用按需加载,而是拆成了多个节点

5.设置缓存

文章中的这一步好像是为了更新用的,并没有什么卵用。而且文件会304走缓存,所以这一步跳过

6.服务端开启GZIP

前端代码方面到我已经想不到什么可以优化的了,那就从服务器端下手吧,服务器有个GZIP的方式,这个还是比较给力的,测试过后,文件在加载的时候下载大小为 74K。到目前位置已经达到了经理的要求,文件估计没办法再缩小了。前端+服务器都把文件大小进行了压缩,还有没有其它途径更快呢?在页面加载的时候,需要把文件下载到本地,对,如果下载的更快,岂不是加载就更快了,那么,进入下一条

7.使用CDN加速

项目使用的阿里云的cdn,我将产出的文件放到cdn上,虽然这样没法上线都要改一次cdn,但是上线不会那么频繁,找一个稳定的版本放在cdn上,果然,页面加载的速度又进了一步。

以上就是前端性能优化的一些步骤!