原文地址javascript
url-loader
會將引入的文件進行編碼,生成 DataURL
,至關於把文件翻譯成了一串字符串,再把這個字符串打包到 JavaScript
。java
通常來講,咱們會發請求來獲取圖片或者字體文件。若是圖片文件較多時(好比一些 icon
),會頻繁發送請求來回請求屢次,這是沒有必要的。此時,咱們能夠考慮將這些較小的圖片放在本地,而後使用 url-loader
將這些圖片經過 base64
的方式引入代碼中。這樣就節省了請求次數,從而提升頁面性能。webpack
url-loader
npm install url-loader --save-dev
webapck
module.exports = { module: { rules: [ { test: /\.(png|jpg|gif)$/, use: [ { loader: 'url-loader', options: {}, }, ], }, ], }, };
import
(或 require
)import logo from '../assets/image/logo.png'; console.log('logo的值: ', logo); // 打印一下看看 logo 是什麼
簡單三步就搞定了。git
webpack
執行 webpack
以後,dist
目錄只生成了一個 bundle.js
。和 file-loader
不一樣的是,沒有生成咱們引入的那個圖片。上文說過,url-loader
是將圖片轉換成一個 DataURL
,而後打包到 JavaScript
代碼中。github
那咱們就看看 bundle.js
是否有咱們須要的 DataURL
:web
// bundle.js (function(module, exports) { module.exports = "data:image/jpeg;base64.........."; // 省略無數行 })
咱們能夠看到這個模塊導出的是一個標準的 DataURL
。npm
一個標準的DataURL:
data:[<mediatype>][;base64],<data>
經過這個 DataURL
,咱們就能夠從本地加載這張圖片了,也就不用將圖片文件打包到 dist
目錄下。json
使用 base64
來加載圖片也是有兩面性的:函數
因此咱們得有取捨,只對部分小 size
的圖片進行 base64
編碼,其它的大圖片仍是發請求吧。工具
url-loader
天然是已經作了這個事情,咱們只要經過簡單配置便可實現上述需求。
limit
的時候使用 fallback
的 loader
來處理文件loader
來處理大於 limit
的文件,默認值是 file-loader
咱們來試試設一個 limit
:
{ test: /\.(png|jpg|gif)$/, use: [ { loader: 'url-loader', options: { limit: 1000, // 大於 1000 bytes 的文件都走 fallback }, }, ], },
從新執行 webpack
,因爲咱們引入的 logo.png
大於 1000
,因此使用的是 file-loader
來處理這個文件。圖片被打包到 dist
目錄下,而且返回的值是它的地址:
(function(module, exports, __webpack_require__) { module.exports = __webpack_require__.p + "dab1fd6b179f2dd87254d6e0f9f8efab.png"; }),
更多關於 file-loader
file-loader
的代碼也很少,就直接複製過來經過註釋講解了:
import { getOptions } from 'loader-utils'; // loader 工具包 import validateOptions from 'schema-utils'; // schema 工具包 import mime from 'mime'; import normalizeFallback from './utils/normalizeFallback'; // fallback loader import schema from './options.json'; // options schema // 定義一個是否轉換的函數 /* *@method shouldTransform *@param {Number|Boolean|String} limit 文件大小閾值 *@param {Number} size 文件實際大小 *@return {Boolean} 是否須要轉換 */ function shouldTransform(limit, size) { if (typeof limit === 'boolean') { return limit; } if (typeof limit === 'number' || typeof limit === 'string') { return size <= parseInt(limit, 10); } return true; } export default function loader(src) { // 獲取 webpack 配置裏的 options const options = getOptions(this) || {}; // 校驗 options validateOptions(schema, options, { name: 'URL Loader', baseDataPath: 'options', }); // 判斷是否要轉換,若是要就進入,不要就往下走 // src 是一個 Buffer,因此能夠經過 src.length 獲取大小 if (shouldTransform(options.limit, src.length)) { const file = this.resourcePath; // 獲取文件MIME類型,默認值是從文件取,好比 "image/jpeg" const mimetype = options.mimetype || mime.getType(file); // 若是 src 不是 Buffer,就變成 Buffer if (typeof src === 'string') { src = Buffer.from(src); } // 構造 DataURL 並導出 return `module.exports = ${JSON.stringify( `data:${mimetype || ''};base64,${src.toString('base64')}` )}`; } // 判斷結果是不須要經過 url-loader 轉換成 DataURL,則使用 fallback 的 loader const { loader: fallbackLoader, options: fallbackOptions, } = normalizeFallback(options.fallback, options); // 引入 fallback loader const fallback = require(fallbackLoader); // fallback loader 執行環境 const fallbackLoaderContext = Object.assign({}, this, { query: fallbackOptions, }); // 執行 fallback loader 來處理 src return fallback.call(fallbackLoaderContext, src); } // 默認狀況下 webpack 對文件進行 UTF8 編碼,當 loader 須要處理二進制數據的時候,須要設置 raw 爲 true export const raw = true;