首页 > 专栏 > 前端 > 文章详情
React 中的代码分割示例 发布于:2021-03-24 15:11:52   来源:React   查看:3  讨论:0
一、打包

大多数 React 应用都会使用 WebpackRollup 或 Browserify 这类的构建工具来打包文件。打包是一个将文件引入并合并到一个单独文件的过程,最终形成一个 “bundle”。接着在页面上引入该 bundle,整个应用即可一次性加载。30g易塔云建站-模板下载,web开发资源,技术博客

// 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

二、代码分割

打包是个非常棒的技术,但随着你的应用增长,你的代码包也将随之增长。30g易塔云建站-模板下载,web开发资源,技术博客
尤其是在整合了体积巨大的第三方库的情况下。你需要关注你代码包中所包含的代码,以避免因体积过大而导致加载时间过长。30g易塔云建站-模板下载,web开发资源,技术博客
为了避免搞出大体积的代码包,在前期就思考该问题并对代码包进行分割是个不错的选择。30g易塔云建站-模板下载,web开发资源,技术博客
代码分割是由诸如 WebpackRollup 和 Browserify(factor-bundle)这类打包器支持的一项技术,能够创建多个包并在运行时动态加载。30g易塔云建站-模板下载,web开发资源,技术博客
对你的应用进行代码分割能够帮助你“懒加载”当前用户所需要的内容,能够显著地提高你的应用性能。30g易塔云建站-模板下载,web开发资源,技术博客
尽管并没有减少应用整体的代码体积,但你可以避免加载用户永远不需要的代码,并在初始加载的时候减少所需加载的代码量。30g易塔云建站-模板下载,web开发资源,技术博客
 30g易塔云建站-模板下载,web开发资源,技术博客

//使用前
import { add } from './math';
console.log(add(16, 26));

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

当 Webpack 解析到该语法时,会自动进行代码分割。如果你使用 Create React App,该功能已开箱即用,30g易塔云建站-模板下载,web开发资源,技术博客
你可以立刻使用该特性。Next.js 也已支持该特性而无需进行配置。30g易塔云建站-模板下载,web开发资源,技术博客
如果你自己配置 Webpack,你可能要阅读下 Webpack 关于代码分割的指南。30g易塔云建站-模板下载,web开发资源,技术博客
你的 Webpack 配置应该类似于此30g易塔云建站-模板下载,web开发资源,技术博客
当使用 Babel 时,你要确保 Babel 能够解析动态 import 语法而不是将其进行转换。对于这一要求你需要 @babel/plugin-syntax-dynamic-import 插件。30g易塔云建站-模板下载,web开发资源,技术博客
30g易塔云建站-模板下载,web开发资源,技术博客
三、React.lazy()30g易塔云建站-模板下载,web开发资源,技术博客
 30g易塔云建站-模板下载,web开发资源,技术博客

//使用前
import OtherComponent from './OtherComponent';

//使用之后
const OtherComponent = React.lazy(() => import('./OtherComponent'));
React.lazy 接受一个函数,这个函数需要动态调用 import()。30g易塔云建站-模板下载,web开发资源,技术博客
它必须返回一个 Promise,该 Promise 需要 resolve 一个 default export 的 React 组件。30g易塔云建站-模板下载,web开发资源,技术博客
然后应在 Suspense 组件中渲染 lazy 组件,如此使得我们可以使用在等待加载 lazy 组件时做优雅降级(如 loading 指示器等)。
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
  return (
      <div>
        <Suspense fallback={<div>Loading...</div>}>
          <OtherComponent />
        </Suspense>
      </div>
  );
}
你甚至可以用一个 Suspense 组件包裹多个懒加载组件。
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AntherComponent = React.lazy(() => import('./AntherComponent'));
function MyComponent() {
  return (
      <div>
        <Suspense fallback={<div>Loading...</div>}>
          <OtherComponent />
          <AntherComponent />
        </Suspense>
      </div>
  );
}
四、捕获异常边界值30g易塔云建站-模板下载,web开发资源,技术博客
如果模块加载失败(如网络问题),它会触发一个错误。30g易塔云建站-模板下载,web开发资源,技术博客
你可以通过异常捕获边界(Error boundaries)技术来处理这些情况,以显示良好的用户体验并管理恢复事宜。
import React, { Suspense } from 'react';
import MyErrorBoundary from './MyErrorBoundary';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
const MyComponent = () => (
    <div>
      <MyErrorBoundary>
        <Suspense fallback={<div>Loading...</div>}>
          <section>
            <OtherComponent />
            <AnotherComponent />
          </section>
        </Suspense>
      </MyErrorBoundary>
    </div>
);
五、理想使用方式:路由
import React, { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const App = () => (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Switch>
          <Route exact path="/" component={Home}/>
          <Route path="/about" component={About}/>
        </Switch>
      </Suspense>
    </Router>
);
一个不错的选择是从路由开始。大多数网络用户习惯于页面之间能有个加载切换过程。你也可以选择重新渲染整个页面,这样您的用户就不必在渲染的同时再和页面上的其他元素进行交互。30g易塔云建站-模板下载,web开发资源,技术博客
30g易塔云建站-模板下载,web开发资源,技术博客
六、js文件集合形式,命名导出
// ManyComponents.js
export const MyComponent = /* ... */;
export const MyUnusedComponent = /* ... */;

// MyComponent.js
export { MyComponent as default } from "./ManyComponents.js";

// MyApp.js
import React, { lazy } from 'react';
const MyComponent = lazy(() => import("./MyComponent.js"));
ManyComponents.js是一个js模块包文件,作为中间路由地址,通过lazy去加载。如此能统一管理,这能保证 tree shaking 不会出错,并且不必引入不需要的组件。

评论

  • 匿名