利用React 16.6新特性优化应用性能

栏目: 服务器 · 发布时间: 5年前

内容简介:利用

利用 懒加载(Lazy Loading) 优化页面性能不是什么新概念,不过React 16.6可以使用 React.lazySuspense 让原生React实现Lazy Loading大大的简化。

本篇文章也会拓展多种类似解决方案,见 拓展 部分

主要关键词说明

动态导入(Dynamic Import)

动态导入 目前只是TC39的一个提案,不是JS(ES)标准的一部分。该功能可以动态化加载我们分割的组件/页面/文件,具体提案见下方链接: TC39 proposal-dynamic-import提案

目前要使用 动态导入 ,需要使用到babel插件:

babel-plugin-syntax-dynamic-import

React.lazy

lazy函数 提供了一种非常简便的方法动态导入组件,实现按需加载与代码分割

点击查看文档

React.lazy使用方式非常简单,示例:

// lazy 接受一个函数作为参数
const MyComponent = React.lazy(() => import('path/MyComponent'));

// 展示时才加载(可以自定义一些条件)
const App = () => (
  <div>
    <MyComponent />
  </div>
)
复制代码

Suspense

Suspense 组件用于包装lazy组件,在lazy组件还没有完全加载时,将fallback内容呈现给用户。

用动态加载,编译时会将文件分割,从加载文件到呈现会有时间延迟,此时可以使用 Suspense 展示一个loading。

点击查看文档

使用示例

import React, { Suspense } from 'react';

const MyComponent = React.lazy(() => import('path/MyComponent'));
const Loading = (
  <h3>loading...</h3>
);

const App = () => (
  <div>
    <Suspense fallback={Loading}>
      <MyComponent />
    </Suspense>
  </div>
)
复制代码

ErrorBoundary

ErrorBoundary(错误边界) ,可以使用ErrorBoundary包装Suspense,当Suspense出错时,统一处理错误。当然 ErrorBoundary 不止可用于Suspense,可以包装任意组件,然后统一处理错误。

实际场景中,可以自己先写一些通用错误页/组件继承自 ErrorBoundary ,然后包装要处理的组件。

也可以在组件的 componentDidCatch 生命周期中单独处理错误。

点击查看文档

应用

性能优化说明

针对React加载的优化,可以分为两类:

  • 页面加载优化
  • 组件加载优化

很明显,React.lazy + Suspense可以很方便的应用于组件加载优化场景。

示例场景

CSR(客户端渲染)应用 多页面的中某个耗时组件的加载

路由层

import React from 'react';
import { BrowserRouter as Router, Route } from 'react-router-dom';

import Header from './header';
import Index from '../pages';
import Welcome from '../pages/welcome';

export default () => (
  <Router>
    <div>
      <Header />

      <Route exact path="/" component={Index}/>
      <Route path="/welcome" component={Welcome}/>
    </div>
  </Router>
);
复制代码

某个存在耗时组件的页面

// welcome.js
import React, { Suspense } from 'react';

// 使用Suspense + React.lazy动态加载的耗时组件
const Content = React.lazy(() => import('../components/content'));

export default () => (
  <div>
    <h1>Welcome</h1>
    <Suspense fallback={<div>loading...</div>}>
      <Content/>
    </Suspense>
  </div>
);
复制代码

说明

假设用webpack编译上面代码产出bundle.js。当进入首页时,加载的bundle.js不会包含Welcome Content部分的代码,切换页面到Welcome时会走网络加载需要的文件。

利用这种方法拆分多个组件时,可以显著的提升首屏时间。

完整示例项目

React-New-Features

说明:该项目主要用于React一些新功能及有意思的用法示例,会持续更新,后面会涉及到 hooks 及最新源码相关,有兴趣的可以star。

拓展

针对SSR(服务端渲染)应用导入性能优化

可以使用 Next.js ,Next.js已支持直接使用dynamic import,并且可以指明什么时候动态导入(服务端/客户端),Next.js对首屏做了很多优化,首屏时,服务端会寻找到最简依赖渲染,具体可以点击前面链接查看文档。示例:

// Next.js 动态导入
const MyComponent = dynamic(import('../components/MyComponent'), {
  ssr: false,
  loading: () => false,
});
复制代码

针对组件的动态加载

针对图片的lazy loading

针对动态请求

  • react-request :对于CSR应用,在不用hooks的情况下,也可以不在componentDidMount中处理请求,让请求更加的优雅。
  • react-async :利用 Render Props + React hooks + Context API 统一处理请求,支持SSR使用

封装 react-request 示例(统一请求处理)

import React from 'react';
import PropTypes from 'prop-types';
import { Fetch } from 'react-request';
// import ReactLoading from 'react-loading';

import config from '../../config';

const CustomFetch = (props) => {
  const { url, children } = props;
  return (
    <Fetch
      {...props}
      url={config.serverUrl + url}
      transformData={data => data.data}
    >
      {({ fetching, failed, data }) => {
        if (fetching) {
          // 正在请求:可以展示loading动画
          // return <ReactLoading type="cylon" color="#2db53f" height="10%" width="10%" />;
        }

        if (failed) {
          // 当前组件请求失败
          // return <h1 className="home">请求失败...</h1>;
        }

        if (data) {
          // 请求成功
          return children(data);
        }

        return null;
      }}
    </Fetch>
  );
};

CustomFetch.propTypes = {
  url: PropTypes.string.isRequired,
};

export default CustomFetch;
复制代码

在组件中使用CustomFetch

buildLinks = () => (
    <div className="links">
      <CustomFetch
        url="/getLinks"
      >
        {data => data.map((item, index) => (
          <a className="item" href={item.url} key={`link-${index}`}>
            <img src={item.icon} className="icon" alt={item.name} />
            <p>{item.name}</p>
          </a>
        ))}
      </CustomFetch>
    </div>
  );
复制代码

以上所述就是小编给大家介绍的《利用React 16.6新特性优化应用性能》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

JavaScript & jQuery

JavaScript & jQuery

David Sawyer McFarland / O Reilly / 2011-10-28 / USD 39.99

You don't need programming experience to add interactive and visual effects to your web pages with JavaScript. This Missing Manual shows you how the jQuery library makes JavaScript programming fun, ea......一起来看看 《JavaScript & jQuery》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具