webpack-图片合并

将打包之后的图片合成精灵图

过去为了减少网页请求的次数,我们需要 "UI设计师" 给我们提供精灵图, 并且在使用时还需要手动的去设置每张图片的位置, 但是有了 webpack 之后我们只需要让 "UI设计师" 给我们提供切割好的图片, 我们可以自己合成精灵图, 并且还不用手动去设置图片的位置

使用合并图片

在看如下的这个案例之前我先为你们提供一些相关素材,方便你们自行去测试,素材下载地址:https://wwe.lanzoui.com/ivIGzwn483a

利用 postcss-sprites / webpack-spritesmith 这两个插件当中的其中一个即可完成,合并图片:

我这里就以 postcss-sprites 来进行演示,首先打开官网:https://www.npmjs.com/package/postcss-sprites

首先需要进行安装一下 postcss-sprites

npm install --save-d postcss-sprites postcss

postcss 在之前的文章当中已经说过这个东西了它是一个工具,它提供了很多插件,前面我们利用 postcss 添加了 css 的一些私有前缀,自动的将 px 转换为了 rem,那么本文当中要讲解的插件其实和之前的用法是一样的,修改 postcss.config.js 添加相关配置:

首先在 plugins 当中添加该插件如下,然后在继续在该插件当中进行进一步的相关配置:

"postcss-sprites": {
}

image-20211118220044199

该插件当中的配置项在官方文档当中已经一一列举了如下图所示:

image-20211118220132053

在如上图的众多配置项当中有一个叫 spritePath 的属性,该属性的含义就是告诉 webpack 合并之后的图片保存到什么地方:

"postcss-sprites": {
    spritePath: "./bundle/images",
}

image-20211118220356099

修改 index.html 内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板文件</title>
</head>
<body>
<p class="animal animal1"></p>
<p class="animal animal2"></p>
<p class="animal animal3"></p>
<p class="animal animal4"></p>

<div class="header header1"></div>
<div class="header header2"></div>
<div class="header header3"></div>
<div class="header header4"></div>
</body>
</html>

配置完毕之后将项目进行打包,效果如下图:

image-20211118220649874

发现经过打包之后只有一张图片了,这就可以说明图片已经被合并了,合并之后的图片如下图所示:

image-20211118221108834

验证了图片合并之后再来看看自动设置打包之后图片所对应的位置,如下图:

image-20211118221726406

发现也进行了设置,然后我们打开, index.html 发现图片访问 404,关于这个图片访问 404 的文章等我后面的文章进行讲解这里我先进行解决一下修改 webpack 的 url-loader 的配置加入如下相关配置:

image-20211118221815851

publicPath: "http://localhost:63342/WebPack/webpack4%E6%A0%B8%E5%BF%83%E5%9F%BA%E7%A1%80/34-webpack-%E5%9B%BE%E7%89%87%E5%90%88%E5%B9%B6/bundle/images"

关于如上 publicPath 的路径值怎么来的,打开打包之后的 index.html 审查元素,打开相关元素的 css 设置的背景然后点击 Open in new tab 就可以得到你机子所对应的地址了如下图:

image-20211118222016469

再次打包,查看效果如下图,访问成功:

image-20211118222100303

通过如上的演示之后发现,所有的图片都打包到了一张当中,那么如果我们想要不用的图片打包到一组当中这该如何实现呢,当然在官方文档当中已经提供了相关的解决方案,可以利用 groupBy 这个属性进行分组打包合并图片,groupBy 接收一个函数,该函数会默认传一个参数进去,参数其实就是需要打包的图片, 然后你就可以在该函数当中进行告诉 webpack 合并图片的时候如何分组,首先我们不管三七二十一先将图片参数打印看一下然后我们在进行实现该函数的分组打包逻辑:

image-20211118224941166

groupBy: (image) => {
    console.log(image);
},

打印了入参的参数之后然后利用webpack打包,在打包的过程当中报错是正常不用管,我们只需要查看一下我们打印的参数即可如下图发现是一个对象:

image-20211118225203685

通过观察如上图的 url 我想按照 url 当中的文件夹名称进行分组,然后就引出了如下的逻辑代码,该函数需要返回一个 Promise 的对象:

image-20211118225833504

groupBy: (image) => {
    // ../images/animal/animal1.png
    let path = image.url.substr(0, image.url.lastIndexOf("/"));

    // ../images/animal
    let name = path.substr(path.lastIndexOf("/") + 1);

    // animal
    return Promise.resolve(name);
},

实现了函数内部的业务之后再次打包,然后观察打包之后的内容发现,不过文件夹下的图片被打包到了不同的精灵图当中如下所示:

image-20211118225946693

如上就是分组合并了,那么如果你想让有的图片需要合并有的不需要合并那么该如何实现呢,当然也是有的可以利用 filterBy 来进行实现,当然它也接收一个函数,函数默认会传递一个参数进去就是需要进行处理的图片对象,如下我写了一个过滤的规则,大概意思就是说不是以 .png 结尾的就不用进行合并:

filterBy: (image) => {
    if (!/\.png$/.test(image.url)) {
        return Promise.reject();
    }
    return Promise.resolve();
}

打包之后的效果如下所示:

image-20211118230728915

其实除了使用正则来进行过滤之后还可以利用在对应的图片路径后面添加参数,然后你在过滤规则的函数当中获取一下该参数,如果设置了该参数就进行合并,没有设置就不需要进行合并就这么简单:

image-20211118231016039

End

posted @ 2021-11-18 22:34  BNTang  阅读(277)  评论(0编辑  收藏  举报