【译】通过React 提供的多种代码分割技术,尽可能的提升页面性能
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>
);
}
在此示例中,HomePage和AboutPage组件使用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有优点,但也存在一些缺点。其中一些好处包括:
- 更快的页面加载时间:通过将关键样式包含在HTML文件中,浏览器可以更快地呈现页面,因为它不需要发出额外的请求来获取关键CSS。
- 改进的首次内容呈现(FCP)和首次输入延迟(FID)指标:FCP和FID是衡量页面何时对用户可用的重要指标。内联关键CSS可以帮助改善这些指标,使页面更加用户友好。
然而,还有一些需要考虑的缺点,例如:
- 增加的HTML文件大小:内联关键CSS会增加HTML文件的大小,这可能会对慢速网络上的用户的页面加载时间产生负面影响。
- 维护问题:如果有许多样式或页面中存在内联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应用程序快速且高效,为用户提供出色的用户体验。