Skip to content

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

@falm

Description

@falm

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

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 ★,转载请注明出处。

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions