使用 Webpack 延迟加载图像
使用require.context自动包含文件夹中的所有图片,并仅在需要时使用动态导入进行加载。这是优化网站(或应用程序)带宽、加载时间和缓存的好方法。
源代码
如何
延迟导入图像
我们可以通过文件加载器将图像作为模块导入,文件加载器可以解析图像并返回其解析路径。
创建一个函数来动态导入()图像,返回其解析的路径并将其设置为<img>
src
属性。
const lazyLoadImage = (imageName, img) => {
import(
/* webpackMode: "lazy-once" */
`./images/${imageName}`
)
.then(src => img.src = src.default)
.catch(err => console.error(err));
};
export default lazyLoadImage;
默认情况下,动态导入会为每个 创建一个新的块imageName
,但我们希望为所有图片创建一个单独的块。为此,我们使用/* webpackMode: "lazy-once" */
来生成一个可以满足所有 调用的惰性加载块import()
。这有助于避免在调用图片时发出额外且不必要的网络请求。阅读webpackMode 列表了解更多信息。
生成图像元素
创建一个函数,生成一个<img>
元素,将其附加到 dom 容器,并运行lazyLoadImage
函数来设置其src
属性。
import lazyLoadImage from './lazyLoadImage';
const generateImage = (container, imageName) => {
const img = document.createElement('img');
container.appendChild(img);
lazyLoadImage(imageName, img);
};
export default generateImage;
获取图像名称
我们需要让每个函数imageName
都能使用它们lazyLoadImage
。使用require.contex从文件夹中导入所有.jpg
图片./images
,并仅匹配它们的名称和扩展名。
const getImagesNames = () => {
const r = require.context('./images', false, /\.jpg$/);
// return an array list of filenames (with extension)
const importAll = (r) => r.keys().map(file => file.match(/[^\/]+$/)[0]);
return importAll(r);
};
export default getImagesNames;
生成所有图像
创建一个名为images.js的 javascript 文件,导入后将延迟加载并生成所有图像。
import getImagesNames from './getImagesNames';
import generateImage from './generateImage';
const images = document.querySelector('#images');
const imagesNames = getImagesNames();
// generate <img> element
// lazy-load each image and set its src attribute
// append <img> to #images container
imagesNames.forEach(name => generateImage(images, name));
延迟加载所有图像
您现在可以延迟导入images.js以在需要时一次生成所有图像。
if (somethingHappen) import(
/* webpackPrefetch: true */
'./images'
);
通过使用webpackPrefetch: true
,标签中会放置一个指向 lazy-chunk 的链接<head>
。浏览器空闲时会下载预取的块,并将其存储在浏览器缓存中以供后续使用。
<link rel="prefetch" as="script" href="0.js">
更多信息请参阅prefetching-preloading-modules和link-rel-prefetch-preload-in-webpack以及preload-prefetch-and-priorities-in-chrome。
笔记
在查看应用时,检查 DevTools 的网络选项卡。确保不要禁用 DevTools 中的缓存,否则预取的区块将无法从缓存中获取。
如果您想在主包中包含images.js,则可以添加webpackMode: "eager"
而不是。webpackPrefetch: true
本文是我的learn-webpack存储库集合的一部分。
进一步阅读
- Juho Vepsäläinen 的代码分割
- David Gilbertson 的100 种使用 webpack 拆分块的正确方法
- Rubens Pinheiro Gonçalves Cavalcante 的webpack-and-dynamic-imports-doing-it-right