webpack 處理圖片資源


圖片引入方式

圖片是前端項目必不可少的靜態資源,在日常開發中,我們可能會在下面三種情況使用圖片:

1.HTML 中通過img標簽等方式引入;

2.CSS 中通過src等方式引入;

3.JavaScript 中使用圖片的 URL 或者內容(比如 Canvas 等);

最笨最直接的方式就是直接寫死線上的地址,例如在頁面中,我們引入 如下:

<img src=”http://cdn.example.com/public/logo.png” /> 

上面地址的 http://cdn.example.com 是一個 CDN 靜態域名,后面是我們完整的路徑,這樣我們上線的時候地址就可以直接看了,我們線下開發的時候可以提前將靜態資源打包好上傳到線上。這樣操作想想就很費勁,而且 CDN 每次靜態資源更新都要需要刷新緩存,如果我們使用 MD5 命名圖片的時候就更麻煩了。

我們在 Webpack 中,則可以使用 loader 的方式完成圖片的引入。例如在 CSS 文件中,直接相對路徑使用背景圖片:

.bg-img{
    backgroud: url('./public/logo.png') no-repeat;
} 

在 HTML 中也可以直接使用相對路徑:

<img src=”./public/logo.png” />

還記得我們之前學過的resolve.alias方式創建一個目錄的alias引用,這種方式不僅僅可以在 JavaScript 中使用,在 HTML 和 CSS 中也可以使用的:

// webpack.config.js
module.exports = {
    resolve: {
        alias: {
            '@assets': Path2D.resolve('./src/assets')
        }
    }
}
<img src=”@assets/public/logo.png” /> 

使用 loader 來加載圖片資源

怎么使用圖片我們了解了,但是怎么讓 Webpack 識別圖片,並且能夠打包輸出呢?這時候就需要借助 loader 了,這里有兩個 loader 可以使用:file-loader 和 url-loader 。

file-loader和url-loader是經常在一些 Webpack 配置中看到的兩個 loader,並且兩個 loader 在一定應用場景上是可以相互替代的,但是對於兩者的區別,很少有人能夠說得清楚,下面介紹下兩者的區別。

  • file-loader:能夠根據配置項復制使用到的資源(不局限於圖片)到構建之后的文件夾,並且能夠更改對應的鏈接;
  • url-loader:包含 file-loader 的全部功能,並且能夠根據配置將符合配置的文件轉換成 Base64 方式引入,將小體積的圖片 Base64 引入項目可以減少 http 請求,也是一個前端常用的優化方式。

下面以url-loader為例說明下 Webpack 中使用方法。首先是安裝對應的 loader:

npm install -D url-loader 

下面我們創建一個項目,目錄結構如下:

|---- package.json    # npm package.json
|---- src
|    |---- assets      # 靜態資源
|        |---- img     # 圖片資源
|             |---- large.png  # 大圖片 超過 1M
|             |---- small-01.png  # 小圖圖片
|             |---- small-02.png  # 大圖片 超過 1M
|             |---- small-03.png  # 大圖片 超過 1M
|    |---- index.css      # css 文件
|    |---- index.html     # html
|    |---- index.js  # js
|---- webpack.config.js    # webpack 配置

首先我們在index.css中引入 small-01.png:

.bg-img{
    backgroud: url(./assets/img/small.png) no-repeat;
}

然后在index.js中引入了index.css和large.png:

import img from './assets/img/large.png'
import style from './index.css'
console.log(img, style);

最后我們在index.html中通過 img 引入large.png:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <img src="./assets/img/large.png" alt="背景圖">
</body>
</html>

這時候我們修改webpack.config.js:

const HTMLPlugin = require('html-webpack-plugin');
 
module.exports = {
    mode: 'development',
    entry: './srcindex.js',
    devtool: false,
    module: {
        rules: [
            {
                test: /\.html$/,
                use: ['html-loader']
            },
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.(png|svg|jpg|gif)$/,
                use: {
                    loader: 'url-loader'
                }
            }
        ]
    },
    plugins: [
        new HTMLPlugin({
            template: './src/index.html'
        })
    ]
 
}

執行webpack后發現,打包出來的文件都比較大,通過查看內容發現,我們的圖片被Base64處理了,然后直接引入了。

這是因為url-loader本身優先是將資源Base64引入的。雖然圖片Base64可以減少 http 請求,但是對於1M+這么大的圖片都Base64處理,范圍增加了 CSS、JavaScript 等文件的大小,而且將這么大的Base64反解成可以使用的圖片渲染出來,時間消耗也是很大的。

所以這時候需要使用url-loader的limit選項來控制不超過一定限制的圖片才使用Base64:

{
     test: /\.(png|svg|jpg|gif)$/,
     use: {
         loader: 'url-loader',
         options: {
            imit: 3*1024
         }
     }
 }

這時候再執行webpack,發現多打出一個ad19429dc9b3ac2745c760bb1f460892.png的圖片,這張圖片就是large.png的圖片,因為超過了limit=3*1024顯示所以沒有被處理成Base64。

繼續查看index.html和main.js(index.js打包出來的文件),發現我們使用large.png的地址都被 Webpack 自動替換成了新的路徑ad19429dc9b3ac2745c760bb1f460892.png。

配置 CDN 域名

一般靜態資源上線的時候都會放到 CDN,假設我們的 CDN 域名和路徑為:http://bd.bxstatic.com/img/,這時候只需要修改output.publicPath即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM