- 
                Notifications
    You must be signed in to change notification settings 
- Fork 40
Description
现代前端开发,已经进入工程化阶段,但是基于浏览器的前端项目的在工程化后,往往会遇到一些性能问题,例如中大型前端项目,依赖库和项目本身的资源过大,加载慢,首屏渲染时间长等性能问题,严重影响用户体验,这个时候工程化的项目就需要适当的进行优化,本文分享一下,我们前端项目已经或将要在打包工具这一层级的优化方法。
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就会对资源进行分析,然后会开起一个网页浏览分析结果:
  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文件来加快网页加载速度。
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 ★,转载请注明出处。

