1.import()函数--所有资源
它返回的是一个promise,你这样用是不行的。
正确使用:
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>
);
};
组件加载的时候,它才去获取图片。即使没有渲染到它,页面上也已经有它存在了。
打包结果:
重点关注红框的两个文件。
如果你的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>
);
};
测试看看:
打包看看:
对比发现import()是动态加载,是组件渲染的时候加载,而不是用到它的时候才去加载图片,而且打包的时候还会出现额外文件。
react-lazyload
就更优雅一些,是用到的时候才去加载图片,而且打包的时候,也不会出现额外的文件。
对比
{/* <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()
,并不是使用的时候才动态加载。
打包看看
和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>
);
};
测试
它和import一样,是在加载组件的时候加载的图片,其实这个库已经是五年前的代码了,很久没有人维护了。
打包看看,也没有出现多余的文件。
建议:react-loadable可以不要再用了。