专栏名称: 前端JavaScript
分享 | 学习 | 交流 | 原创 分享是学习的开始;学习不必要从头开始,是从现在开始;交流能沟通你我,提高你的学识;期待你的加入!!! web前端技术交流,JavaScript,HTML5,CSS3……
目录
相关文章推荐
51好读  ›  专栏  ›  前端JavaScript

[S3-E369]React + webpack 之性能优化

前端JavaScript  · 公众号  · Javascript  · 2017-06-22 08:18

正文

本文:【第3章第369回】 更多文章点击 目录 查看


一句很经典的话:没到性能瓶颈的时候,最好不要随意的优化。


1.性能问题

性能问题归根到底就是项目越来越大,文件越来越复杂,导致webpack打包的bundle.js的包越来越大,页面加载也就变的越来越慢。



使用chrome 的 performance分析代码,可以很明显的看到,主要的时间都花在了Evaluate script上面,但这部分我目前没有找到解决方案,所以只能从所以js包的体积入手。


2.基本的解决方案

1. 从webpack入手,webpack本身会有一些插件的优化方法。


    1.UglifyJsPlugin 压缩代码的插件(这个可以很显著的缩小包的体积)

    

    new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }),

    

    2.CommonsChunkPlugin (合并代码)


两个用法:一个是抽取公共的包,另一个则是把多个保重的公共依赖抽取出来


抽取公共包可以优化整体包的体积,一般用在开发环境,可以加快rebuild的速度

抽取公共依赖可以优化整体包的体积,即可以一次下载多次使用,后面的包因为公共依赖的被提取,包的体积减小,可以加快运行速度。

抽出公共代码(可以抽出一些公用模块,降低整个项目但也仅仅只能减少js下载的时间,并不能减少Evaluate script的时间,并且这还会使得两个包的总体积变大),


new webpack.optimize.CommonsChunkPlugin({

      names: ['vendor'],

      filename: '[name].js',

      minChunks: Infinity

    })

    3.Defineplugin

这个插件用来定义全局变量,在webpack打包的时候会对这些变量做替换。这里替换成了production,react代码中有很多的NODE_ENV变量判断


  new webpack.DefinePlugin({ //

      'process.env': {

        NODE_ENV: JSON.stringify('production')

      }

    })

2. 从代码层面入手


1.首先你应该要知道code splitting这个东西,这个是代码层面优化的根基。


code splitting,就是代码分割,简而言之就是代码分割成一个个小块,每次页面加载时,我只需要加载那些我需要的部分(加载包的体积变小了),这样可以让页面加载的更快。


那么如何实现呢?


  • route层面入手

    route2-3中有一个叫做getComponent的方法,可以配置按需加载route,即原来A,B,C三个界面生成一个bundle.js的包,使用了按需加载之后,会变为一个bundle.js包加上3个chunk包,这个时候bundle.js包加上三个chunk包的总大小会比原来的bundle.js包稍微大一点,但是我想进入A界面,我只需要加载bundle.js包和A的chunk包,那么我的A页面加载速度便会变得快许多。

    可以参考另一篇文章React-router 4 按需加载的实现方式及原理(Code Splitting)

  • 实际代码入手1.先学会分析代码,分析代码结构,分析你的包中到底是什么东西如此之大。

    借助工具:

    npm install webpack-visualizer-plugin webpack-stats-plugin --save-dev

    配置:

 import:

    const StatsWriterPlugin = require('webpack-stats-plugin').StatsWriterPlugin;

    const Visualizer = require('webpack-visualizer-plugin');

    

 plugin:

     new StatsWriterPlugin({

      fields: null,

      stats: { chunkModules: true }

    }),

     new Visualizer({

      filename: './statistics.html'

    })

正常的webpack run 之后,会在你的output的地方出现statistics.html这个文件,直接用网页打开就可以了



这样就可以分析出你到底是什么导致你bundle.js报如此之大了,但有一些包我们是无法缩减的,例如react-dom,react,但是绝大部分的包都是可以进行缩减的.


那么如何缩减呢?


加入你这个界面中用到了一个三方的图形控件,例如你用了Echart,那么这个包总是很大的,即使是最小的也有300k左右,其实你其他的代码可能都不到100k,那么这300k将会非常影响你这个界面的加载速度,所以需要给这个控件做一个按需加载,这样可以先展示其余的这100k所展示的界面,等待其余的300k下载好了再把Echart给补上。


代码实现:


1.npm install bundle-loader --save-dev


2.需要些这样一个 Bundle.js,无法点击则代码在最底部


3.


    import EchartContainer from 'bundle-loader?lazy!echart';

    import { bundle } from '../../../components/Bundle';

    

    constructor(props) {

        super(props);

        this.Echart = bundle(EchartContainer);

   }

   

   

    render() {

        return (

     

         

          {

              (this.props.history.isFetching || this.props.monthly.isFetching) &&

             

               

             

          }

     

);

      }

   


3 代码 Bundle.js


import React from 'react';

import PropTypes from 'prop-types';


class Bundle extends React.Component {

  state = {

    // short for "module" but that's a keyword in js, so "mod"

    mod: null

  }


  componentWillMount() {

    // 加载初始状态

    this.load(this.props);

  }


  componentWillReceiveProps(nextProps) {

    if (nextProps.load !== this.props.load) {

      this.load(nextProps);

    }

  }


  load(props) {

    // 重置状态

    this.setState({

      mod: null

    });

    // 传入组件的组件

    props.load((mod) => {

      this.setState({

        // handle both es imports and cjs

        mod: mod.default ? mod.default : mod

      });

    });

  }


  render() {

    // if state mode not undefined,The container will render children

    return this.state.mod ? this.props.children(this.state.mod) : null;

  }

}


Bundle.propTypes = {

  load: PropTypes.func,

  children: PropTypes.func

};



export default Bundle;

export function bundle(item) {

  return props =>

   

      {Component => }

    ;

}


转自: https://segmentfault.com/a/1190000009792759

作者: zhiwei


>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

如果文章不错,请转发的朋友圈!

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


==========阅读原文==========