React 性能优化:网络性能(自动化按需加载)

1,253 阅读3分钟

在性能优化中,有一块很重要的部分 -- 网络性能优化(自动化按需加载)

什么是自动化按需加载呢?在应用加载的过程中,我们不会将所有的资源一次性加载到前端;而是选择在切换页面/功能时,再加载其相关的资源。

如何在 React 中实现按需加载?

  • 使用 Webpack 提供的 import API,实现模块按需切割加载的功能。
  • 使用 react-loadable 库实现 React 异步加载。

代码分割

打包

打包是一个将文件引入并合并到一个单独文件的过程,最终形成一个 “bundle”。接着在页面上引入该 bundle,整个应用即可一次性加载。

  • App 文件:
// app.js
import { add } from './math.js';
console.log(add(16, 26)); // 42
// math.js
export function add(a, b) {
  return a + b;
}
  • 打包后文件:
function add(a, b) {
  return a + b;
}

console.log(add(16, 26)); // 42

代码分割

随着应用迭代/完善,你的代码包也将随之增长,尤其是在整合了体积巨大的第三方库的情况下;此时,需要思考如何避免因体积过大而导致加载时间过长?

为了避免搞出大体积的代码包,在前期就思考代码分割是个不错的选择。代码分割能够提供“Lazy Loading (懒加载)” -- 只加载当前用户所需要的内容,这可以显著地提高应用性能。尽管并没有减少应用整体的代码体积,但可以避免加载用户永远不需要的代码,并在初始加载的时候减少所需加载的代码量。

import()

引入代码分割的最佳方式是通过动态 import() 语法。

  • 使用之前:
import { add } from './math';

console.log(add(16, 26));
  • 使用之后:
import('./math').then((math) => {
  console.log(math.add(16, 26));
});

Webpack 解析到该语法时,会自动进行代码分割。如果你使用 Create React App,该功能已开箱即用,你可以立刻使用该特性。Next.js 也已支持该特性而无需进行配置。

React Loadable

React Loadable 是一个很小的库,Loadable 是一个高阶组件用来轻易地在组件层面拆分 bundle。

安装

yarn add react-loadable

Loadable 的用法很简单。你仅仅要做的就是把要加载的组件和当你加载组件时的 Loading 组件传入一个方法中。

import Loadable from 'react-loadable';
import Loading from './my-loading-component';

const LoadableComponent = Loadable({
  loader: () => import('./my-component'),
  loading: Loading,
});

const App = () => {
  return <LoadableComponent />;
};

export default App;

实战

lazy.gif 我们在之前的项目基础上,添加按需加载。可以看到,在之前的项目中切换不同的 Tab,Network 的资源加载是不会新增,也就是说所有的资源在一开始都加载进来了。

对于组件的代码是无需改动的,我们只需在路由中配置按需加载。

首先引入 Loadable,将静态导入改造为动态导入(() => import('./pages/xxx')),最后返回高级函数(Loadable)处理后的组件。

// App.js
import Loadable from 'react-loadable';

const routers = [
  {
    name: 'Form',
    path: '/form',
    loader: () => import('./pages/form'),
  },
  {
    name: 'DynamicForm',
    path: '/dynamic-form',
    loader: () => import('./pages/dynamicForm'),
  },
  {
    name: 'Multiple Request',
    path: '/multiple-request',
    loader: () => import('./pages/multipleRequest'),
  },
  // ...
];

function Loading() {
  return <div>Loading...</div>;
}

{
  routers.map(({ path, loader }) => {
    const Component = Loadable({
      loader,
      loading: Loading,
    });
    return (
      <Route key={path} path={path}>
        <Component />
      </Route>
    );
  });
}

效果

import.gif

切换项目 Tab 时,Network 中加载了新的文件,这个文件就是 Tab 页相关的资源。

借助 chrome 的开发者工具,我们调慢网速来看一下 loading 状态。loading 显示正常 OK。 network.gif

【不知道如何用 chrome 开发者工具 调整网速的小伙伴,看这里 ⬇️】

network-1.png

network-2.png

代码

完整项目代码,看这里

参考资料

React 性能优化