react 懒加载汇总

453 阅读3分钟

1.import()函数--所有资源

它返回的是一个promise,你这样用是不行的。

image.png

正确使用:

import { useState, useEffect } from 'react';

export default function App() {
  const [img1, setImg1] = useState<any>();
  const [img2, setImg2] = useState<any>();


  useEffect(() => {
    import('./assets/img.png').then((val) => {
      console.log(val, 111);
      setImg1(val.default);
    });
    import('./assets/img2.png').then((val) => {
      setImg2(val.default);
    });
  }, []);

  return (
    <div>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <img src={img1} /><br />
      <img src={img2} />
    </div>
  );
};

组件加载的时候,它才去获取图片。即使没有渲染到它,页面上也已经有它存在了。

image.png

打包结果:

image.png

重点关注红框的两个文件。

如果你的webpack不支持import()动态加载,就记得配置

// webpack.config.js
const path = require('path');
 
module.exports = {
  mode: 'development', // 或 'production'
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js',
    chunkFilename: '[name].[chunkhash].js',
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react'],
            plugins: ['@babel/plugin-syntax-dynamic-import'],
          },
        },
      },
    ],
  },
};

2.react-lazyload组件-所有资源

安装:

npm install --save react-lazyload
npm install --save-dev @types/react-lazyload 
npm install --save prop-types

代码:

import img1 from './assets/img.png';
import img2 from './assets/img2.png';
import LazyLoad from 'react-lazyload';

export default function App() {
  return (
    <div>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <LazyLoad placeholder={<div>loading...</div>}>
        <img src={img1} />
      </LazyLoad>
      <LazyLoad placeholder={<div>loading...</div>}>
        <img src={img2} />
      </LazyLoad>
    </div>
  );
};

测试看看:

image.png 打包看看:

image.png

对比发现import()是动态加载,是组件渲染的时候加载,而不是用到它的时候才去加载图片,而且打包的时候还会出现额外文件。

react-lazyload就更优雅一些,是用到的时候才去加载图片,而且打包的时候,也不会出现额外的文件。

image.png 对比

      {/* <LazyLoad placeholder={<div>loading...</div>}>
        <Home></Home>
      </LazyLoad> */}

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

<Home></Home>

发现import()把组件home单独打包了,但是LazyLoad却没有

3. 使用React.lazy()函数--仅组件

React.lazy()函数是React 16.6版本引入的新特性,可以用于懒加载组件

写两个组件看看:

组件1

const Img2 = () => {
  return <img src='./assets/img2.png' />;
};

export default Img2;

组件2


const Img1 = () => {
  return <img src='./assets/img.png' />;
};

export default Img1;

导入

import React, { Suspense, lazy } from 'react';
const ImgCom1 = lazy(() => import('./Img1'));
const ImgCom2 = lazy(() => import('./Img2'));

export default function App() {
  return (
    <div>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <Suspense fallback={<div>Loading...</div>}>
        <ImgCom1></ImgCom1>
        <ImgCom2></ImgCom2>
      </Suspense>
    </div>
  );
};

效果类似 import() ,并不是使用的时候才动态加载。

image.png

打包看看

image.png

和import()相比较,它并没有出现额外的js文件。

4.react-loadable库--仅组件

react-lazyload是以组件的形式懒加载组件或者其他资源,react-loadable是以函数的形式加载组件。

安装:

npm i react-loadable -S

npm i --save-dev @types/react-loadable

上代码:

在vite里面的react项目里面没法使用 react-loadable, 会报错,需要在webpack里面使用。

还有在vite里面我们的图片可以直接加载,这样使用:

     <img src='./img.png'/>

在webpack里面这样使用会报错,必须这样使用:

import ningmo from './img.png';
<img src={ ningmo} />

代码:

img组件

import img from './img.png';
const Img1 = () => {
  return <img src={img} />;
};

export default Img1;

app代码

import Loadable from 'react-loadable';

const Img1 = Loadable({
  loader: () => import('./Img1'),
  loading: () => <div>Loading...</div>,
});

const Img2 = Loadable({
  loader: () => import('./Img2'),
  loading: () => <div>Loading...</div>,
});



export default function App() {
  return (
    <div>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <p>xxxxxx</p>
      <Img1></Img1><br />
      <Img2></Img2>
    </div>
  );
};

测试

image.png

它和import一样,是在加载组件的时候加载的图片,其实这个库已经是五年前的代码了,很久没有人维护了。

打包看看,也没有出现多余的文件。

image.png

建议:react-loadable可以不要再用了。