原文地址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;