BooheeFE/weekly

2018/06/11 - 前端项目性能优化之打包工具篇

falm opened this issue · 6 comments

falm commented

现代前端开发,已经进入工程化阶段,但是基于浏览器的前端项目的在工程化后,往往会遇到一些性能问题,例如中大型前端项目,依赖库和项目本身的资源过大,加载慢,首屏渲染时间长等性能问题,严重影响用户体验,这个时候工程化的项目就需要适当的进行优化,本文分享一下,我们前端项目已经或将要在打包工具这一层级的优化方法。

webpack为目前较为流行的前端项目打包工具,它提供了丰富的扩展功能和插件来让我们对项目有更好的控制,我司前端项目也是使用webpack来作为打包工具,接下来的介绍也是围绕在它来进行。

打包性能分析

要做性能优化,首先要知道优化哪些部分,也就是哪些比较慢,通常情况下,最直观的方向就是,项目整体打包文件的大小的问题,如果资源过大,那么网站性能肯定是上不去的。我们这里使用Webpack Bundle Analyzer 这个工具来分析一下,项目打包后各个模块所占用的资源情况。

首先安装:yarn add webpack-bundle-analyzer —dev

然后在webpack 配置文件中,将webpack-bundle-analyzer 加入到插件上:

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
......
plugins: [new BundleAnalyzerPlugin()]

之后我们在production模式下构建项目,NODE_ENV=production yarn build BundleAnalyzerPlugin就会对资源进行分析,然后会开起一个网页浏览分析结果:

612D9821-75FB-4C17-AAA1-BB9CF82567F1.png

  13.f4b485a6e42f8d1022b1.js    14.4 kB      13  [emitted]
   0.f4b485a6e42f8d1022b1.js    56.3 kB       0  [emitted]
   2.f4b485a6e42f8d1022b1.js    42.9 kB       2  [emitted]
   3.f4b485a6e42f8d1022b1.js    39.2 kB       3  [emitted]
   4.f4b485a6e42f8d1022b1.js    47.9 kB       4  [emitted]
   5.f4b485a6e42f8d1022b1.js    8.96 kB       5  [emitted]
   6.f4b485a6e42f8d1022b1.js     4.1 kB       6  [emitted]
   7.f4b485a6e42f8d1022b1.js      97 kB       7  [emitted]
   8.f4b485a6e42f8d1022b1.js    40.4 kB       8  [emitted]
   9.f4b485a6e42f8d1022b1.js    14.8 kB       9  [emitted]
  10.f4b485a6e42f8d1022b1.js    15.7 kB      10  [emitted]
  11.f4b485a6e42f8d1022b1.js    12.3 kB      11  [emitted]
  12.f4b485a6e42f8d1022b1.js      23 kB      12  [emitted]
   1.f4b485a6e42f8d1022b1.js    68.4 kB       1  [emitted]
  14.f4b485a6e42f8d1022b1.js    12.4 kB      14  [emitted]
  15.f4b485a6e42f8d1022b1.js    68.7 kB      15  [emitted]
  16.f4b485a6e42f8d1022b1.js    12.4 kB      16  [emitted]
  17.f4b485a6e42f8d1022b1.js    12.3 kB      17  [emitted]
  18.f4b485a6e42f8d1022b1.js    13.7 kB      18  [emitted]
  19.f4b485a6e42f8d1022b1.js    8.46 kB      19  [emitted]
  20.f4b485a6e42f8d1022b1.js     5.3 kB      20  [emitted]
  21.f4b485a6e42f8d1022b1.js    6.08 kB      21  [emitted]
  22.f4b485a6e42f8d1022b1.js    2.13 kB      22  [emitted]
  23.f4b485a6e42f8d1022b1.js    3.03 kB      23  [emitted]
  24.f4b485a6e42f8d1022b1.js  500 bytes      24  [emitted]
main.f4b485a6e42f8d1022b1.js     533 kB      25  [emitted]  [big]  main

第三方库CDN

通过分析结果我们可以看到,第三方库如Lodash 占据了资源文件不小空间,这个我们就可以使用webpack本身提供的external功能,通过CDN加速的lodash。

配置如下:

{
    externals: {
     lodash: '_',
  },
}

然后我们在项目的入口html中收到加入CDN link:

<!doctype html>
<html class="no-js" lang="">
  <head>
	...
  </head>
  <body>
    <div id="container"></div>
    <script src="https://cdn.bootcss.com/lodash.js/4.17.4/lodash.min.js"></script>
    <script src="<%= bundle %>"></script>
    <script src="<%= vender %>"></script>
  </body>
</html>

公共模块提取

优化了上一部分的CDN,其实项目当中有些没有CDN的第三方资源我们也可用通过提取公共模块的方式,把它们单独的打包成一个文件,这样就可以让main.js的体积进一步减小,浏览器也能够并行加载资源。

这里要使用的就是Webpack提供的CommonsChunkPlugin 插件

配置:

{
   entry: {
    main:  './main.js',
    vendor: ['react', 'react-dom', 'react-redux']
  },
  plugins: [new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor' // 公共模块的入口
  })]
}

配置之后,webpack就会将 react一系列的资源,单独打包成一个vendor.js文件来加快网页加载速度。

525F3CBE-F438-4B0E-9682-204D1F5806B9.png

CSS拆分

最后一个我们要说的性能优化是CSS,在我们的前端项目中使用了 css modules和react技术,项目中的cs s就会打包在js文件当中,当网页加载好js代码后,再作为内联样式渲染,这里就带来了一个弊端,样式的渲染不能和js代码的加载同时进行,需要等到js加载完后才可以,解决办法就是将项目中的所有css文件,提取出来作为一个外联的css文件,这样网页在加载时就会首先加载样式表文件,然后进行解析渲染,不需要等js加载完成。

那么我们要做的就是使用extract-text-webpack-plugin 插件来做到样式表提取。

安装:yarn add extract-text-webpack-plugin —dev

配置:

const ExtractTextPlugin = require("extract-text-webpack-plugin");

{
  module: {
    rules: [
            { //提取css文件
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          // use: "css-loader"
          use: [
            {
              loader: 'css-loader',
              options: {
                // sourceMap: isDebug,
                sourceMap: false,
                importLoaders: true,
                // CSS Modules https://github.com/css-modules/css-modules
                modules: true,
                minimize: !isDebug,
              },
            },
          ],
        })
      },
      { // 提取scss文件
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          //resolve-url-loader may be chained before sass-loader if necessary
          // use: ['css-loader', 'sass-loader']
          use: [
            {
              loader: 'css-loader',
              options: {
                sourceMap: false,
                importLoaders: true,
                // CSS Modules https://github.com/css-modules/css-modules
                modules: true,
                localIdentName: isDebug ? '[name]_[local]_[hash:base64:3]' : '[hash:base64:4]',
                // CSS Nano http://cssnano.co/options/
                minimize: !isDebug,
              },
            },
            {
              loader: 'sass-loader'
            }
          ],

        })
      },
    ]
  }
  
  plugins: [ // 加载插件,并且指定输出css的文件路径名。
    config.plugins.push(new ExtractTextPlugin('[name].css?[hash]'));
  ]
}

最后的效果就是我们从原来输出一个大的主文件,变成了三个文件,main.js的大小533kb减小到了264kb,少了一倍。

  main.40e4cd0b400a3812526a.js     264 kB      25  [emitted]  [big]  main
vendor.40e4cd0b400a3812526a.js     170 kB      26  [emitted]         vendor
 main.css?40e4cd0b400a3812526a    28.1 kB      25  [emitted]         main

结尾

以上介绍的三种打包工具层面的优化,我们就可以看到 路由和webpack本身已经使用了code split技术将我们的页面拆分成了数字编号的小文件,这就是按需加载。前端性能优化中资源大小的优化属于第一步骤,后续更深入的优化,包括运行时优化,渲染优化,数据加载优化等等,之后我们有机会再来介绍。

广而告之

本文发布于薄荷前端周刊,欢迎Watch & Star ★,转载请注明出处。

欢迎讨论,点个赞再走吧 。◕‿◕。 ~

点赞👍。一点小小的建议:有一些错别字,特别是CSS拆分那里,导致有些句子不通顺,如果创建Issue前检查一遍,那就更棒了。

wusb commented

@Lupeipei 已修改,谢谢您的建议。

100cm commented

uglify,rollup 一个都没提到。。。,性能优化 体积只是其中一小部分,,还有加载,缓存。。

wusb commented

@100cm 嗯 这次只提到了打包工具,后续会逐渐出其他系列的,欢迎Watch & Star。😊

100cm commented

@simbawus 把文章写的深入一些才值得star 和 watch。

vue,router,vuex放到cdn会更好