通过React 提供的多种代码分割技术,尽可能的提升页面性能

avatar
web前端开发

【译】通过React 提供的多种代码分割技术,尽可能的提升页面性能

原文地址:edvins.io/react-code-…

React是一个流行的用于构建用户界面的JavaScript库,但随着应用程序规模的增长,JavaScript包的大小可能会变得很大,导致加载时间变慢,性能下降。为了解决这个问题,React提供了几种代码分割技术,允许你将代码分割成较小的块,减小初始JavaScript包的大小,提高应用程序的性能。

在这篇博客文章中,我们将介绍React的以下几种代码分割技术:

  • 常用的代码分割实现方式
    • 动态导入
    • React Lazy与Suspense
    • Loadable组件
  • 高级技术
    • 基于路由的代码分割
    • 预加载
    • 关键CSS的内联
    • 动态快

常用的代码分割实现方式

在React中,有许多将代码分割成较小块并按需加载的方法。因此,我们将介绍在React中实现代码分割的比较流行的方法。

动态导入

动态导入允许将代码分割成较小块并按需加载,而不是一次性加载所有内容。使用动态导入,您可以确保只加载特定功能所需的代码,从而实现较小的初始JavaScript包和更好的性能。

import React, { useState, useEffect } from 'react';

const HomePage = () => {
  const [module, setModule] = useState(null);

  useEffect(() => {
    import('./HomePageWidget').then((mod) => setModule(mod.default));
  }, []);

  return module ? <module /> : <div>Loading...</div>;
};

React Lazy与Suspense

React Lazy是一个高阶组件,允许您延迟加载组件,即在需要时按需加载。使用React Lazy,您可以确保应用程序仅加载所需的元素,减小初始JavaScript包的大小并提高性能。

import React, { lazy, Suspense } from 'react';

const HomePage = lazy(() => import('./HomePage'));

const App = () => (
  <Suspense fallback={<div>Loading...</div>}>
    <HomePage />
  </Suspense>
);

Loadable组件

Loadable Components是一个高阶组件,允许您将代码拆分为较小的块,并按需加载它们,就像React Lazy一样。使用Loadable Components,您可以指定在代码块加载时显示的加载组件。

import React from 'react';
import loadable from '@loadable/component';

const HomePage = loadable(() => import('./HomePage'), {
  fallback: <div>Loading...</div>,
});

const App = () => <HomePage />;

高级技术

现在我们了解了一些实现基本代码拆分的方法,让我们使用它们来创建更高级的技术。

基于路由的代码分割

基于路由的代码拆分是一种优化技术,通过仅加载特定路由所需的代码来提高Web应用程序的性能。这可以显著减少浏览器需要下载和解析的JavaScript量,从而加快加载时间,改善整体用户体验。

路由代码拆分的另一个优点是,在应用程序不断增长时,它可以实现更好的可扩展性。随着应用程序变得越来越大,JavaScript包的大小可能变得难以处理,导致加载时间过长和性能不佳。通过根据路由将代码拆分成较小的块,开发人员可以确保只加载必要的代码,即使应用程序不断增长,也能改善性能。

import React, { lazy, Suspense } from 'react';

const HomePage = lazy(() => import('./HomePage'));
const AboutPage = lazy(() => import('./AboutPage'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Route exact path="/" component={HomePage} />
      <Route path="/about" component={AboutPage} />
    </Suspense>
  );
}

在此示例中,HomePageAboutPage组件使用lazy函数进行异步加载。Suspense组件在加载组件时提供了一个加载中的用户界面。这样,浏览器只会下载和解析特定路由所需的代码,从而提高应用程序的性能。

预加载

预加载是一种技术,在用户与应用程序交互时,可以在后台加载代码块。这确保了在需要代码的时候再去加载代码块,减少了加载时间,并提高了应用程序的整体性能。

以下是在React中使用React.lazy函数实现预加载的示例:

import React, { lazy, Suspense } from 'react';

const LazyComponent = lazy(() => import('./LazyComponent'));

function App() {
  return (
    <>
      <Suspense fallback={<div>Loading...</div>}>
        <LazyComponent />
      </Suspense>
    </>
  );
}

export default App;

在上面的示例中,使用React.lazy函数来进行懒加载加载LazyComponent组件。Suspense组件用于在LazyComponent加载时提供一个fallback的UI。

在这个示例中,当用户与应用程序的其他部分进行交互时,LazyComponent将在后台进行加载。当用户导航到LazyComponent时,它将立即加载,提供流畅无缝的体验。

关键CSS的内联

内联关键CSS涉及将页面初始视图所需的样式直接包含在HTML文件中,而不是从单独的CSS文件加载。这减少了加载样式所需的时间,提高了应用程序的性能。

内联关键CSS有优点,但也存在一些缺点。其中一些好处包括:

  1. 更快的页面加载时间:通过将关键样式包含在HTML文件中,浏览器可以更快地呈现页面,因为它不需要发出额外的请求来获取关键CSS。
  2. 改进的首次内容呈现(FCP)首次输入延迟(FID)指标:FCP和FID是衡量页面何时对用户可用的重要指标。内联关键CSS可以帮助改善这些指标,使页面更加用户友好。

然而,还有一些需要考虑的缺点,例如:

  1. 增加的HTML文件大小:内联关键CSS会增加HTML文件的大小,这可能会对慢速网络上的用户的页面加载时间产生负面影响。
  2. 维护问题:如果有许多样式或页面中存在内联CSS更改,将关键CSS内联到HTML文件中的维护可能变得复杂。

总的来说,内联关键CSS有时可能是一种适当的优化技术,但在应用程序中实施之前权衡利弊是至关重要的。

以下是使用styled-components库在React应用程序中内联关键CSS的示例:

import React from 'react';
import styled, { createGlobalStyle } from 'styled-components';

const GlobalStyle = createGlobalStyle`
  /* Your critical CSS rules */
  .header {
    background-color: blue;
  }
`;

const Header = styled.header`
  /* Your non-critical CSS rules */
  color: white;
  font-size: 20px;
`;

function App() {
  return (
    <>
      <GlobalStyle />

      <Header className="header">Welcome to my React App!</Header>
    </>
  );
}

export default App;

在这个例子中,关键的CSS规则使用styled-components库的createGlobalStyle方法在GlobalStyle组件中定义。这些样式将被内联到HTML文件中,并且立即可供浏览器使用,无需额外的CSS文件。

Header组件使用styled方法定义非关键的CSS规则,这些规则可以作为单独的CSS文件在后续加载。这样,关键样式可用于页面的初始视图,提高性能,而非关键样式稍后加载,对性能影响较小。

动态块

动态代码块允许您将代码拆分为更小、更可管理的部分,可以按需加载。这种方法可以显著提高应用程序的性能,通过减少一次性加载和执行的代码量。

动态代码块与动态导入和React Lazy类似,但有一个重要的区别。使用动态代码块,您可以指定代码块名称和文件名,从而更好地控制代码拆分过程。这使您能够仅加载当前应用程序状态所需的代码,提高性能并减少应用程序加载所需的时间。

通过使用动态代码块,您还可以改善代码库的组织。通过将代码拆分为更小的部分,您可以更好地管理特定部分的加载和执行。这可以使您更容易维护和调试代码,并使其在未来的开发中更具可扩展性。

// largeFile.js
export const ComponentA = React.lazy(() => import('./ComponentA'));
export const ComponentB = React.lazy(() => import('./ComponentB'));
// index.js
import React, { lazy, Suspense } from 'react';
import { ComponentA, ComponentB } from './largeFile';

function App() {
  return (
    <>
      <Suspense fallback={<div>Loading...</div>}>
        <ComponentA />
        <ComponentB />
      </Suspense>
    </>
  );
}

通过上述代码,React只在需要时加载ComponentA和ComponentB,而不是一次性加载所有组件。这可以显著提高应用程序的性能,因为它减少了一次性加载和执行的代码量。

这篇文章涵盖了所有最新的React代码拆分技术,并提供了代码示例,帮助您在React应用程序中实现这些技术。通过这些技术,您可以确保您的React应用程序快速且高效,为用户提供出色的用户体验。