前言

在日常的 React 项目开发中,这些错误会让你的项目变慢。实际上如果你熟悉 Vue 项目的开发话,这些道理是相同的。这边文章分析的是路由懒加载和图片懒加载。

路由懒加载

  • 通过 React.lzay() 实现组件的动态加载
  • import() 拆包
  • 优化性能不需要一次加载全部的 js 文件

例子:

import { createBrowserRouter, RouterProvider } from "react-router-dom";

import Home from "./pages/Home";

const router = createBrowserRouter([
  {
    path: "/",
    element: <Home />,
  },
]);

变成

import { createBrowserRouter, RouterProvider } from "react-router-dom";

const Home = React.lazy(() => import("./pages/Home"));

const router = createBrowserRouter([
  {
    path: "/",
    element: (
      <Suspense fallback={<>loading....</>}>
        <Home />
      </Suspense>
    ),
  },
]);

在打包的时候也会根据懒加载而将文件进行分割。减小了首页 JS 文件的大小。

在组件中,对于子组件来说,也是通过 lazy导入模块配合 Suspense来使用

const Test = React.lazy(() => import("./_components/Test"));

export default function Wrapper() {
  return (
    <Suspense fallback={<>loading</>}>
      <Test />
    </Suspense>
  );
}

这样不仅会在加载的时候不干扰其他的组件加载,同时还能显示骨架屏。

图片懒加载

为什么要做图片懒加载呢,因为图片资源很多的话,会一直在请求下载,会对网站造成卡顿。所以我们应该暂时不加载那些看不见的图片。

这里用的 JS 自带的 IntersectionObserver函数,具体可以去MDN上看他的说明。

这里提供一个封装的 Image 懒加载的组件,以供参考

export default function LazyLoad(props: LazyLoadProps) {
  const [inView, setInView] = useState(false);
  const [ref, setRef] = useState(null);
  const fallback = (entries, observer) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        setInView(true);
      }
    });
  };

  useEffect(() => {
    let observer = new IntersectionObserver(fallback);

    if (ref?.current) {
      observer.observe(ref.current);
    }

    return () => {
      // if(ref?.current){
      // 	observer.unobserver(ref.current);
      // }
      observer.disconnect();
    };
  }, []);

  return inView ? (
    <img {...props} />
  ) : (
    <img
      {...props}
      ref={ref}
      style={{ width: "1000px", height: "1000px", backgroundColor: "red" }}
    />
  );
}