《释放路由懒加载的力量: 最佳实践到源码分析》


初始化项目

create-react-app demo
cd demo
npm i react-router-dom
  • 主要相关依赖的版本如下:
{
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.14.1"
  }
}

未使用路由懒加载

根目录\src\index.js

import React from "react";
import ReactDOM from "react-dom/client";
import { Routes, Link, HashRouter as Router, Route } from "react-router-dom";
import Home from "./components/Home";
import User from "./components/User";

function App() {
  return (
    <>
      <ul>
        <li>
          <Link to="/">Home</Link>
        </li>
        <li>
          <Link to="/user">User</Link>
        </li>
      </ul>

      <Routes>
        <Route path="/" exact={true} element={<Home />} />
        <Route path="/user" element={<User />} />
      </Routes>
    </>
  );
}

const root = ReactDOM.createRoot(document.querySelector("#root"));
root.render(
  <Router>
    <App />
  </Router>
);

根目录\src\components\Home.js

import React from "react";

const arr = Array(1000).fill(0);
export default function Home() {
  return (
    <>
      {arr.map((item, index) => (
        <p key={index}>我是Home组件---{item}</p>
      ))}
    </>
  );
}

根目录\src\components\User.js

import React from "react";

const arr = Array(1000).fill(0);
export default function User() {
  return (
    <>
      {arr.map((item, index) => (
        <p key={index}>我是User组件---{item}</p>
      ))}
    </>
  );
}
  • 对上面的代码存在的问题进行分析:

      1. 我们都知道 React 的脚手架是基于 webpack 来配置的。
      • 可能很多小伙伴会觉得很奇怪:我们并没有在目录结构中看到任何 webpack 相关的内容?
      • 原因是 React 脚手架将 webpack 相关的配置隐藏起来了,我们可以执行 npm run eject 看到 webpack 的配置信息
      1. 那么项目同样会被 webpack 打包后生成一个 bundle.js 文件。
      1. 而如果通过上面的方式,那么加载首页的时候,Home 组件和 User 组件都会被打包到 bundle.js 中,然后项目启动后就会去请求加载资源(包括 bundle.js),进而渲染页面。
      • 在这里插入图片描述

      • 在这里插入图片描述

      • 在这里插入图片描述

      1. 如果随着我们的路由组件的业务代码越来越复杂,代码量越来越大,那么相应打包后的 bundle.js 文件体积就会越来越大,请求加载资源的速度就会变慢,这就可能会严重影响到页面的首屏加载。
      1. 因此我们可以使用路由懒加载进行优化,即切换到哪个路由然后再去加载该路由对应的组件
      1. 懒加载的本质:直接将组件单独打包成一个分片,然后路由切换的时候去动态的加载这个切片

使用路由懒加载优化

根目录\src\utils.js

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

const loading = () => <div>Loading...</div>;

/**
 * 实现路由的分割
 * @param {*} loadComponent () => import("./components/Home")
 * @returns
 */
export const dynamic = (loadComponent) => {
  let LazyComponent = lazy(loadComponent);
  return () => (
    <Suspense fallback={loading}>
      <LazyComponent />
    </Suspense>
  );
};

根目录\src\index.js

+import { dynamic } from "./utils";

-import Home from "./components/Home";
-import User from "./components/User";

+const LazyHome = dynamic(() => import("./components/Home"));
+const LazyUser = dynamic(() => import("./components/User"));

function App() {
  return (
    <>
      <ul>
        <li>
          <Link to="/">Home</Link>
        </li>
        <li>
          <Link to="/user">User</Link>
        </li>
      </ul>

      <Routes>
-        <Route path="/" exact={true} element={<Home />} />
-        <Route path="/user" element={<User />} />

+        <Route path="/" exact={true} element={<LazyHome />} />
+        <Route path="/user" element={<LazyUser />} />
      </Routes>
    </>
  );
}
  • 通过上面的代码,我们可以知道的路由懒加载的使用步骤:

      1. 通过 () => import("./components/Home") 的方式拿到原路由组件
      1. 将其传给 React.lazy(), 得到一个新的组件
      1. 再使用 <Suspense> 组件将 新组件 包裹起来
      • <Suspense> 组件的 fallback 属性可接收一个组件,在加载时显示该组件
  • 使用路由懒加载后:

      1. 我们可以看到当项目启动后
      • 在这里插入图片描述
      1. 当切换路由到 User 组件的时候
      • 在这里插入图片描述
      1. 并且会发现 bundle.js 文件不再有 Home 组件和 User 组件的代码
      • 在这里插入图片描述

手写实现路由懒加载

  • 即实现 React.lazy()
function lazy(load) {
  return class extends React.Component {
    state = { Component: null };
    componentDidMount() {
      // import("./components/Home") 返回的是一个 promise
      load().then((result) => {
        // console.log(result)  // result 其实是一个 webpack 编译后的模块,其 default 属性该模块的组件
        this.setState({ Component: result.default });
      });
    }
    render() {
      let { Component } = this.state;
      return Component && <Component />;
    }
  };
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值