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.

相關文章
相關標籤/搜索