07_02_加载图片(Webpack Book)

Loading Images(加载图片)

HTTP/1 application can be made slow by loading a lot of small assets as each request comes with an overhead. HTTP/2 helps in this regard and changes the situation somewhat drastically. Till then you are stuck with different approaches. Webpack allows a few of these.
HTTP/1应用程序由于加载许多小资源来降低速度,因为每个请求都会带来开销。HTTP/2在这方面提供了帮助,并大大改变了这种情况。在此之前,你只能用其他方法。Webpack允许其中的一些方法。

Webpack can inline assets by using url-loader. It emits your images as base64 strings within your JavaScript bundles. The process decreases the number of requests needed while growing the bundle size. It's enough to use url-loader during development. You want to consider other alternatives for the production build, though.
Webpack可以通过url-loader内嵌资源。它把图片转换成BASE64字符串嵌入到Javascript包中。这个操作在增加了包的大小的同时减少了请求数量。在开发阶段使用url-loader足以。但是需要为生产环境考虑其他的替代方案。

Webpack gives control over the inlining process and can defer loading to file-loader. file-loader outputs image files and returns paths to them instead of inlining. This technique works with other assets types, such as fonts, as you see in the later chapters.
Webpack提供了对内联过程的控制并可以延迟加载到file-loader
file-loader输出图片文件并返回它们的路径而不是内联。这个技术也适用于其他资源,例如在后面章节介绍的字体。

Setting Up url-loader(设置url-loader)

url-loader is a good starting point and it's the perfect option for development purposes, as you don't have to care about the size of the resulting bundle. It comes with a limit option that can be used to defer image generation to file-loader after an absolute limit is reached. This way you can inline small files to your JavaScript bundles while generating separate files for the bigger ones.
url-loader是一个好的开端并且它是它是用于开发目的的完美选择, 因为你不用担心结果包的大小。它有一个limit选项,在超出尺寸限制时,可以用来将图片的生成推迟到file-loader。这个方式可以让你将小文件嵌入到Javascript包中,而将大文件独立生成。

If you use the limit option, you need to install both url-loader and file-loader to your project. Assuming you have configured your styles correctly, webpack resolves any url() statements your styling contains. You can point to the image assets through your JavaScript code as well.
如果你要使用 limit选项,就需要同时在项目中安装 url-loaderfile-loader。假设你已经配置好了样式文件,webpack会处理样式中包含的所有url()语句。你也可以通过Javascript代码指向图片资源。

In case the limit option is used, url-loader passes possible additional options to file-loader making it possible to configure its behavior further.
limit选项使用时,url-loader尽可能传递额外选项给 file-loader, 使其可以进一步配置。

To load .jpg and .png files while inlining files below 25kB, you would have to set up a loader:
为了加载内联文件大小小于25kb的.jpg.png 文件,就需要配置一个加载器:

{
  test: /\.(jpg|png)$/,
  use: {
    loader: "url-loader",
    options: {
      limit: 25000,
    },
  },
},

T> If you prefer to use another loader than file-loader as the limit is reached, set fallback: "some-loader". Then webpack will resolve to that instead of the default.
在达到 limit 限制的文件大小时,如果你想用别的加载器而不是 file-loader, 需要设置 fallback:"some-loader". 然后Webpack就会使用新的加载器来替换默认的。

Setting Up file-loader(设置 file-loader)

If you want to skip inlining altogether, you can use file-loader directly. The following setup customizes the resulting filename. By default, file-loader returns the MD5 hash of the file's contents with the original extension:
如果希望直接跳过内联(资源),可以直接使用 file-loader。下面的配置自定义了生成文件的文件名,默认情况下,file-loader返回文件内容的MD5哈希值和文件原有的扩展名。

{
  test: /\.(jpg|png)$/,
  use: {
    loader: "file-loader",
    options: {
      name: "[path][name].[hash].[ext]",
    },
  },
},

T> If you want to output your images below a particular directory, set it up with name: "./images/[hash].[ext]".
如果你希望将图片文件在特定目录输出,按以下方式配置 name: "./images/[hash].[ext]"

W> Be careful not to apply both loaders on images at the same time! Use the include field for further control if url-loader limit isn't enough.
一定要注意不要在图片上同时使用两个加载器!如果 limit选项不能满足进一步控制时,需要使用include字段。

Integrating Images to the Project(将图片集成到项目中)

The ideas above can be wrapped in a small helper that can be incorporated into the book project. To get started, install the dependencies:
上面的想法可以封装成一个小的帮助模块来合并进本书的项目中。开始前,先安装依赖项:

npm install file-loader url-loader --save-dev

Set up a function as below:
如下配置一下工具:

webpack.parts.js

exports.loadImages = ({ include, exclude, options } = {}) => ({
  module: {
    rules: [
      {
        test: /\.(png|jpg)$/,
        include,
        exclude,
        use: {
          loader: "url-loader",
          options,
        },
      },
    ],
  },
});

To attach it to the configuration, adjust as follows. The configuration defaults to url-loader during development and uses both url-loader and file-loader in production to maintain smaller bundle sizes. url-loader uses file-loader implicitly when limit is set, and both have to be installed for the setup to work.
按下面的修改方法将load-images附加到配置中。在开发过程中,配置默认为url-loader,而在生产环境中,为了减小包的大小而使用url-laderfile-loaderurl-laderlimit选项设置后隐式调用 file-loader,并且只能安装并配置后才能正常工作。

webpack.config.js

const productionConfig = merge([
  ...
leanpub-start-insert
  parts.loadImages({
    options: {
      limit: 15000,
      name: "[name].[ext]",
    },
  }),
leanpub-end-insert
]);

const developmentConfig = merge([
  ...
leanpub-start-insert
  parts.loadImages(),
leanpub-end-insert
]);

To test that the setup works, download an image or generate it (convert -size 100x100 gradient:blue logo.png) and refer to it from the project:
要测试配置是否正常工作,下载一个图片或者生成一个(convert -size 100x100 gradient:blue logo.png) 并在项目中引用这个图片:

src/main.css

body {
  background: cornsilk;
leanpub-start-insert
  background-image: url("./logo.png");
  background-repeat: no-repeat;
  background-position: center;
leanpub-end-insert
}

The behavior changes depending on the limit you set. Below the limit, it should inline the image while above it should emit a separate asset and a path to it. The CSS lookup works because of css-loader. You can also try importing the image from JavaScript code and see what happens.
由于 limit 设置的改变,行为而发生改变。小于 limit时,图片会被内联到文件中,而当图片大小 limit 时,它会对图片生成一个独立的资源和路径。由于有 css-loader, CSS 查询才能工作。你也可以尝试在Javascript代码中导入图片并查看会发生什么。

Loading SVGs(加载SVG文件)

Webpack allows a couple ways to load SVGs. However, the easiest way is through file-loader as follows:
Webpack允许几个方法来加载SVG文件。然而,最简单的方法还是下面这种通过 file-loader 的方法:

{
  test: /\.svg$/,
  use: "file-loader",
},

Assuming you have set up your styling correctly, you can refer to your SVG files as below. The example SVG path below is relative to the CSS file:
假设已经正确设置了你的样式,你可以按下面的方式引用SVG文件。例子中SVG文件是CSS文件的相对路径:

.icon {
   background-image: url("../assets/icon.svg");
}

Consider also the following loaders:
也可以考虑使用下面的加载器:

  • raw-loader gives access to the raw SVG content.
  • raw-loader 可以访问SVG文件的内容。
  • svg-inline-loader goes a step further and eliminates unnecessary markup from your SVGs.
  • svg-inline-loader 更进一步并且避免SVG文件中不必要的标记。
  • svg-sprite-loader can merge separate SVG files into a single sprite, making it potentially more efficient to load as you avoid request overhead. It supports raster images (.jpg, .png) as well.
  • svg-sprite-loader 可以将不同的SVG文件合并成一个文件,可以通过避免过度请求让加载效率更加有效。它也支持光栅图片(.jpg, .png).
  • svg-url-loader loads SVGs as UTF-8 encoded data urls. The result is smaller and faster to parse than base64.
  • svg-url-loader 将SVG文件加载为UTF-8编码数据url,结果更小并且转换速度比base64更多快。
  • react-svg-loader emits SVGs as React components meaning you could end up with code like <Image width={50} height={50}/> to render a SVG in your code after importing it.
  • react-svg-loader 将SVG文件生成React组件,这意味着当你在代码中导入SVG文件后可以将代码写成<Image width={50} height={50}/>这种方式来渲染SVG文件。

T> You can still use url-loader and the tips above with SVGs too.
你仍然可以在SVG文件上使用 url-loader 和上面的技巧。

Optimizing Images(优化图片)

In case you want to compress your images, use image-webpack-loader, svgo-loader (SVG specific), or imagemin-webpack-plugin. This type of loader should be applied first to the data, so remember to place it as the last within use listing.
如果你想压缩图片,可以使用 image-webpack-loader, svgo-loader (仅限SVG), 或者 imagemin-webpack-plugin. 这类加载器应该最先应用到数据上,所以记住将他放在use列表的下面。

Compression is particularly valuable for production builds as it decreases the amount of bandwidth required to download your image assets and speed up your site or application as a result.
压缩对生产环境构建是非常有用的,因为它在下载图片资源时能减少带宽请求,最终加速你的站点或者应用。

Utilizing srcset(利用srcset)

resize-image-loader and responsive-loader allow you to generate srcset compatible collections of images for modern browsers. srcset gives more control to the browsers over what images to load and when resulting in higher performance.
resize-image-loaderresponsive-loader 帮你为现代浏览器生成 srcset图片兼容合集 . srcset让浏览器能够更好地控制要加载什么图像,以及什么时候可以获得更高的性能。

Loading Images Dynamically(动态加载图片)

Webpack allows you to load images dynamically based on a condition. The techniques covered in the Code Splitting and Dynamic Loading chapters are enough for this purpose. Doing this can save bandwidth and load images only when you need them or preload them while you have time.
Webpack允许你根据条件动态加载图片。Code SplittingDynamic Loading两章进行了详细的描述。这样做可以节省带宽,并且只有在需要的时候加载图片以及有时间的情况下加载预先加载图片。

Loading Sprites(加载精灵表单)

Spriting technique allows you to combine multiple smaller images into a single image. It has been used for games to describe animations and it's valuable for web development as well as you avoid request overhead.
Spriting 技术可以让你将多个更小的文件合并成一个图片。它曾被用在游戏中来生成动画并且它也对避免过量请求很有帮助。

webpack-spritesmith converts provided images into a sprite sheet and Sass/Less/Stylus mixins. You have to set up a SpritesmithPlugin, point it to target images, and set the name of the generated mixin. After that, your styling can pick it up:
webpack-spritesmith 将提供的图片转换成精灵表单以及 Sass/Less/Stylus 混合体. 你不得不设置一个 SpritesmithPlugin, 将它指向目标图片,并指定生成的混合体的名字,之后,你的样式可以使用它了:

@import "~sprite.sass";

.close-button {
  sprite($close);
}

.open-button {
  sprite($open);
}

Using Placeholders(使用占位符)

image-trace-loader loads images and exposes the results as image/svg+xml URL encoded data. It can be used in conjunction with file-loader and url-loader for showing a placeholder while the actual image is being loaded.
image-trace-loader 加载图片并以 image/svg+xml URL编码的方式输出。它可以与 file-loaderurl-loader一起使用, 在实际图片加载的位置显示一个占位符。

lqip-loader implements a similar idea. Instead of tracing, it provides a blurred image instead of a traced one.
lqip-loader 实现了类似的想法. 它不跟踪,而是提供一个模糊图像替代跟踪图像。

Getting Image Dimensions(获取图片尺寸)

Sometimes getting the only reference to an image isn't enough. image-size-loader emits image dimensions, type, and size in addition to the reference to the image itself.
有时仅获得图片的引用是不够的。 image-size-loader 生成了对图片引用以外的尺寸,类型和大小。

Referencing to Images(引用图片)

Webpack can pick up images from style sheets through @import and url() assuming css-loader has been configured. You can also refer to your images within the code. In this case, you have to import the files explicitly:
css-loader如果已经被配置好,Webpack可以通过 @importurl() 在式样文件中导入图片。你也可以在代码中引用图片。这种情况下,你必须显式的导入文件。

import src from "./avatar.png";

// Use the image in your code somehow now
const Profile = () => <img src={src} />;

If you are using React, then you use babel-plugin-transform-react-jsx-img-import to generate the require automatically. In that case, you would end up with code:
如果你在使用React,然后使用babel-plugin-transform-react-jsx-img-import 自动生成 require。这种情况下,你应该这样处理代码:

const Profile = () => <img src="avatar.png" />;

It's also possible to set up dynamic imports as discussed in the Code Splitting chapter. Here's a small example:
代码分离一节也讨论了如何配置动态导入。下面是个小例子:

const src = require(`./avatars/${avatar}`);`.

Images and css-loader Source Map Gotcha(图片和 css-loader 代码映射问题)

If you are using images and css-loader with the sourceMap option enabled, it's important that you set output.publicPath to an absolute value pointing to your development server. Otherwise, images aren't going to work. See the relevant webpack issue for further explanation.
如果你在使用图片并打开了 css-loader* 的 sourceMap 选项, 配置output.publicPath将其指向开发服务器的绝对径很重要. 否则,图片将无法工作。 参考 the relevant webpack issue 获取更多信息。

Conclusion(总结)

Webpack allows you to inline images within your bundles when needed. Figuring out proper inlining limits for your images requires experimentation. You have to balance between bundle sizes and the number of requests.
Webpack允许你在必要的时候将图片嵌入到程序包中。计算出准确的嵌入图片大小(limit option)需要进行实验。你必须平衡包的尺寸和请求的数量。

To recap:(概要)

  • url-loader inlines the assets within JavaScript. It comes with a limit option that allows you to defer assets above it to file-loader.
  • url-loader 将资源嵌入到Javascript中. 它有一个 limit 选项,当图片大小超过该值时,将图片传递给 file-loader处理.
  • file-loader emits image assets and returns paths to them to the code. It allows hashing the asset names.
  • file-loader 生成图片资源并将图片路径返回给代码. 它可以将哈希值加入到资源名称中.
  • You can find image optimization related loaders and plugins that allow you to tune their size further.
  • 图片优化相关的加载器和插件让你能进一步调整图片的尺寸。
  • It's possible to generate sprite sheets out of smaller images to combine them into a single request.
  • 可以将多个小图片生成sprite sheets(精灵表单), 把他们合并进一个请求(减少客户端请求数量).
  • Webpack allows you to load images dynamically based on a given condition.
  • Webpack允许基于条件动态加载图片。
  • If you are using source maps, you should remember to set output.publicPath to an absolute value for the images to show up.
  • 如果你在使用源码映射, 要记住将图片的绝对路径设置给 output.publicPath 来让图片正确显示。

You'll learn to load fonts using webpack in the next chapter.

相关推荐