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容许其中的一些方法。javascript

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足以。可是须要为生产环境考虑其余的替代方案。css

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输出图片文件并返回它们的路径而不是内联。这个技术也适用于其余资源,例如在后面章节介绍的字体。java

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包中,而将大文件独立生成。react

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代码指向图片资源。webpack

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, 使其能够进一步配置。git

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

{
  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就会使用新的加载器来替换默认的。web

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哈希值和文件原有的扩展名。npm

{
  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.

相关文章
相关标签/搜索