加载大量小的资源会使基于 HTTP/1 的应用变慢,因为每个请求都会产生开销。HTTP/2 在这方面有所改善,并且在某种程度上改变了这种情况。除此之外,Webpack 也有一些解决办法。
Webpack 可以使用 url-loader 内联资源。它会将您的图像转为 base64 形式的字符串,从而减少 HTTP 请求,但是它会增加打包结果的尺寸。在开发过程中,我们可以使用这种方式,生产环境可能不太适合。
Webpack 可以控制内联过程,然后使用 file-loader 对其延迟加载。file-loader 能够将导入的图片存放到特定的目录,并返回图片的路径地址。此技术适用于其他类型的资源,例如字体,后面的章节也会提到。
url-loader
是一个很好的起点,它是开发环境的完美选择,因为您不必关心生成的 bundle 的大小。它带有一个 limit 选项,当达到绝对限制后将图像交给 file loader 处理。这样,您可以将小文件内联到 JavaScript 包中,同时为较大的文件生成单独的请求地址。
如果要使用 limit 选项,则需要在项目中安装 url-loader 和 file-loader。假设您已正确配置样式,webpack 将解析样式中任何包含 url() 的语句。您也可以通过 JavaScript 代码指向图像资源。
在使用 limit 选项的情况下,url-loader 将可能的附加选项传递给 file-loader,从而可以让 file-loader 进一步配置其行为。
要在内联 25kB 以下的文件时加载 .jpg
和 .png
文件,您可以这样设置 loader:
module.exports = {module: {rules: [{test: /\.(jpg|png)$/,use: {loader: 'url-loader',options: {limit: 25000,},},},],},};
当
limit
限制生效时,如果你想使用另一个 loader,而不是file-loader
的话,你可以在配置中添加fallback: "some-loader"
。然后 Webpack 就会使用这个 loader 而不是采取默认行为。
如果要完全跳过内联,可以直接使用 file-loader
。以下配置自定义了生成的文件名。默认情况下,file-loader 使用文件内容的 MD5 哈希值和扩展名组合称新的文件名:
module.exports = {module: {rules: [{test: /\.(jpg|png)$/,use: {loader: 'file-loader',options: {name: '[path][name].[hash].[ext]',},},},],},};
如果要将图像输出到特定目录下,请在配置中这样设置
name: "./images/[hash].[ext]"
。
注意不要同时在图像上同时应用两个 loader!如果 url-loader
limit
不够,请使用include
字段进一步控制。
Webpack 允许几种方式加载 SVG。但是,最简单的方法是通过 file-loader
:
{test: /\.svg$/,use: "file-loader",}
现在,我们就可以在文件中引入 SVG 了。下面的 SVG 路径是相对于 CSS 文件的:
.icon {background-image: url('../assets/icon.svg');}
我们还可以考虑以下 loader:
.jpg
和 .png
格式的图像<Image width={50} height={50} />
来渲染 SVG 元素。如果你想压缩图片,请使用 image-webpack-loader、svgo-loader(专用于 SVG)或 imagemin-webpack-plugin。注意,此类型的 loader 应用于最终的数据,因此请记住,将其作为 use
列表中的最后一个来执行。
压缩对于生产构建特别有价值,因为它减少了下载图像时所需的带宽量,从而加快了站点或应用程序的速度。
resize-image-loader 和 responsevie-loader 允许您为现代浏览器生成 srcset
属性所需要的图像集合。srcset
属性可以让浏览器决定加载哪些图像以及何时提高性能。
Spriting 技术允许您将多个较小的图像组合成单个图像。它已经被用于游戏中的动画,但对于 Web 开发也很有价值,因为它节省了很多请求开销。
webpack-spritesmith 将提供的图像转换为 sprite 图和一些 Sass/Less/Stylus mixin。您必须设置 SpritesmithPlugin 插件,将其指向目标图像,并设置生成的 mixin 的名称。之后,你的 样式就可以使用它了:
image-trace-loader 加载图像并将结果编码为 image/svg+xml
格式的 URL 数据。它可以于 file-loader
和 url-loader
一起使用,以便在加载实际图像时显示占位符。
lqip-loader 实现了类似的功能,它不显示占位符,而是 i 工一个模糊的图像。
有时只获得对图像的引用是不够的。除了返回图像本身的引用之外,image-size-loader 还会返回图像尺寸、类型和大小。
如果配置好了 css-loader
,Webpack 可以通过 @import
从样式表中获取图像。JS 代码中也可以引用图像。在这种情况下,您必须在文件中显式地导入:
import src from './avatar.png';// 在代码中可以使用图片了const Profile = () => <img src={src} />;
如果您使用的是 React,那么您可以使用 babel-plugin-transform-react-jsx-img-import 自动生成 require
。在这种情况下,您的代码可以精简成下面的样式。
const Profile = () => <img src="avatar.png" />;