React.memo性能比React.PureComponent差

dra*_*fly 5 reactjs

前段时间我对单元渲染器组件进行了重构以实现性能提升(我有一个巨大的表).我从功能无状态组件到重构PureComponent.例如:

import React from 'react';
import PropTypes from 'prop-types';

class SomeCell extends React.PureComponent {
  render() {
    const { pizzaOrder } = this.props;
    return (
      <>
        {pizzaOrder.name}
        <br />
        {pizzaOrder.price}
      </>
    );
  }
}

SomeCell .propTypes = {
  pizzaOrder: PropTypes.object,
};

export default SomeCell ;
Run Code Online (Sandbox Code Playgroud)

现在我看到React.memo被释放,所以我更新react@16.6.0react-dom@16.6.0(从16.5.2)和重构,从PureComponentReact.memo与期望,这将是更快(没有生命周期方法调用函数的内存比小类等):

import React from 'react';
import PropTypes from 'prop-types';

const SomeCell = React.memo(function({ pizzaOrder }) {
  return (
    <>
        {pizzaOrder.name}
        <br />
        {pizzaOrder.price}
    </>
  );
});

SomeCell .propTypes = {
  pizzaOrder: PropTypes.object,
};

export default SomeCell;
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,表现明显下降.

你知道它有什么问题吗?

prod模式下的配置文件数据(没有chrome中的插件)显示之前发生的脚本编写得更多PureComponent(我的案例的脚本编写时间从0.5秒增加到3.8秒).

编辑:经过一些调查,似乎它不是React.memo的问题,而是新版本的React.我已将单元格渲染器还原为PureComponent并保留了新的react@16.6.0版本,结果(性能显着降低)仍然存在

rar*_*dev 6

正如@skyboyer所建议的那样,在React Repository中创建了一个问题.

问题摘要(2018-11-11):

  • 这个问题与React本身无关,而与uglify-es(错误)优化无关.
  • uglify-es 是内联代码(不应该内联).
  • uglify-es 不再积极维护.
  • 建议的解决方案是terser用作替代品.
  • 如果您正在使用uglifyjs-webpack-plugin或Webpack 4.xx(uglifyjs-webpack-plugin默认使用),您应该更改webpack配置中的minifier选项,如下所示:

    const TerserWebpackPlugin = require('terser-webpack-plugin');
    
    module.exports = {
      //...
      optimization: {
        minimizer: [
          new TerserWebpackPlugin({ /* your config */ })
        ]
      }
    };
    
    Run Code Online (Sandbox Code Playgroud)


Ida*_*gan 5

TL; DR:

将webpack升级到版本4.26

因为他们切换到terser作为默认的最小化器.

背景:

  • uglifyjs-webpack-plugin <v1.0使用了缩放器 uglify-js
  • 但是uglify-js不支持ES6,这导致了一个名为fork的分支uglify-es,它是在uglify-js存储库中开发的,但是在harmony分支下
  • uglifyjs-webpack-pluginv1.x切换到uglify-esES6支持
  • 然而uglify-es停止维护:mishoo/UglifyJS2#3156(评论)
  • 这导致了一个名为fork的分支terser,它已经整合了所有未开发的PR,并将成为所有新开发的地方:https: //github.com/fabiosantoscode/terser
  • terser-webpack-plugin已创建,terser相当于uglifyjs-webpack-plugin:https: //github.com/webpack-contrib/terser-webpack-plugin
  • uglifyjs-webpack-pluginv2.x将切换回uglify-js,因此任何需要支持ES6的项目现在都需要切换到 terser-webpack-plugin.

参考: webpack/commit