towebp-loader誕生記~ 一個webpack 圖片loader

冰星寒水發表於2017-03-20

在上篇Vuejs webp圖片支援,外掛開發過程~ 中我做了一個圖片轉換成webp的元件,並且使用了相關的loader,但是我們在使用過程中發現webp和原圖的hash是不一樣的,這樣我們就沒有辦法保留版本的概念了,臨時我使用時間戳來作為替代,但是這樣每次上傳都會重新上傳所有檔案,有點浪費硬碟,於是我今天做了這個towebp-loader

功能

towebp-loader 可以在webpack中根據圖片型別轉換成一份webp和原圖兩份圖片,並且整合了url-loader的功能 支援url的limit功能和file-loader檔名的功能。

使用方法

{
     test: /.(png|jpe?g|gif|svg)(?.*)?$/,
     loader: `towebp?` + JSON.stringify({
       limit: 10000,
       name: utils.assetsPath(`fonts/[name].[hash:7].[ext]`)
      })
},

配合vue-webp指令使用效果更佳哦

vue-webp
使用方法

![](abc.jpg)

關鍵原始碼講解

……
// 獲取loader中的查詢字串 使用webpack loader api
var query = loaderUtils.parseQuery(this.query);
 // 儲存原始檔的路徑如果穿 name就使用不然使用預設hash.ext模式
var url = loaderUtils.interpolateName(this, query.name || "[hash].[ext]", {
    content: content,
    regExp: query.regExp
});
// webp 檔案的儲存路徑
var webpUrl = url.substring(0, url.lastIndexOf(`.`)) + `.webp`;
// limit引數來自url-loader 如果小於這個值使用base64字串替換圖片
if (query.limit) {
  limit = parseInt(query.limit, 10);
}
var mimetype = query.mimetype || query.minetype || mime.lookup(this.resourcePath);
if (limit <= 0 || content.length < limit) {
  return "module.exports = " + JSON.stringify("data:" + (mimetype ? mimetype + ";" : "") + "base64," + content.toString("base64"));
}
……
// 轉換原圖成webp
imagemin.buffer(content, { plugins: [imageminWebp(options)] }).then(file => {
  // 儲存原圖
  this.emitFile(url, content);
  // 儲存壓縮後的webp圖片
  this.emitFile(webpUrl, file);
  callback(null, "module.exports = __webpack_public_path__ + " + JSON.stringify(url) + ";");
}).catch(err => {
  callback(err);
});
……

主要程式碼都在這裡了。還有一些webpack loader的API 大家仔細去讀相關文件

參考

webp-loader
url-loader
file-loader

相關文章