浅谈 Webpack 如何处理图片(开发、打包、优化)


Posted in Javascript onMay 15, 2019

从 webpack book 的 Loading Assets 一章中延申出来。

改善前端项目体验中,很重要的点就是静态资源的优化。它是由于浏览器客户端在同一时间针对同一 域名 的请求有一定资源限制。如果资源过多、过大就会使得页面卡顿。

静态资源中,又以图片最为典型。那么我们在开发中该如何处理图片呢?

webpack 是前端较为常用的手脚架工具,本文以它为例。

主要分为 开发 、 打包 、 优化 三个方面来介绍

示例地址: webpack demo

开发

webpack 可以用使用url-loader  将静态图片转化为 base64 编码的字符串,并内联在对应的脚本中。大幅度地较少了页面的请求数,所以在开发阶段可以无限制地使用。具体方法

// npm install url-loader --save-dev

rules: [{
  test: /\.(png|jpg)$/,
  use: {
    loader: 'url-loader',
  },
}]

以 demo-example 为例,Gakki.jpg 被转化为了 base 64 编码的图片。在开发阶段,没什么问题,但是如果在实际环境中,会发现一个很大的问题,将图片越大转化为base 64 编码的字符串就越长,将会导致整个 Js 脚本的大小飙升。

打包

为了减小脚本的大小,我们需要告诉 webpack 什么情况下采用 url-loader 去内联图片,什么情况下采用其他的 loader。所以首先需要对 url-loader 进行配置

rules: [{
  test: /\.(png|jpg)$/,
  use: {
    loader: 'url-loader',
   options: {
      limit: 15000,
      name: '[name].[ext]',
    },
  },
}]

在 options 中设定一个阈值属性 limit: 15000 ,表明当图片小于该阈值 15kb 时,采用内联形式加载。那么如果超过阈值,我们该怎么办?

可以利用 fallback 属性指定采用file-loader  来处理,具体见配置

options: {
  limit: 15000,
 fallback: 'file-loader',
  name: 'images/[name].[hash].[ext]',
},

默认情况下,file-loader 会返回 options 依据 文件内容返回一个 MD5 Hash 来构建文件名。

如果同时需要 file-loader 与 url-loader 的情况,需要设置 limit来做区分。

优化

为了进一步地优化体验,我们可以采用以下策略:

  1. 控制图片质量,压缩图片大小;
  2. 配置 <img /> 标签的 srcset 来适应不同的屏幕;
  3. 合成雪碧图,减少图片资源请求数;
  4. 使用占位图。

控制图片质量,压缩图片大小

为了和 url-loader 配合,引入image-webpack-loader ,同时配置图片的 loader

{
  test: /\.(png|jpg)$/,
  use: [
    {
      loader: 'url-loader',
      // 同上
      options,
    },
    {
      loader: 'image-webpack-loader',
      // 配置不同图片的质量
      options: {
        mozjpeg: {
          progressive: true,
          quality: 65,
        },
        optipng: {
          enabled: true,
        },
        pngquant: {
          quality: '65-90',
          speed: 4,
        },
        gifsicle: {
          interlaced: false,
        },
        webp: {
          quality: 75,
        },
      },
    },
  ],
}

然后运行 npm run build ,很明显的发现,图片的大小有了明显的变化。这种对于图片的压缩对于生产环境特别有价值,因为它减少了下载图像资源所需的带宽量,从而加快了站点或应用程序的速度。

也可以采用 imagemin-webpack-plugin 插件。

配置 <img /> 标签的 srcset 来适应不同的屏幕

resize-image-loader 和responsive-loader 可以生成 srcset 的图片合集,可以在现代游览器上获得更好地体验,同时可以更好地控制浏览器加载哪些图像以及何时获得更高的性能。

合成雪碧图,减少图片资源请求数

Spriting技术允许将多个较小的图像组合成单个图像。它对于Web开发很有价值,同时也避免了请求开销。

webpack-spritesmith 能够生成雪碧图和 Sass / Less / Stylus mixins。必须设置 SpritesmithPlugin,将其指向目标图像,并设置生成的mixin的名称。

使用占位图

与以上对比,这个 loader 使用起来相对复杂,它加载图像并将其转化为 image / svg + xml URL 编码数据。通常它可以与file-loader和url-loader一起使用,以便在加载实际图像时显示占位符。配置为

{
  test: /\.(gif|png|jpe?g)$/i,
    use: [
      {
        loader: 'image-trace-loader'
      },
      {
        loader: 'url-loader',
        options: {
          limit: 8192
        }
      }
    ]
}

这样,你在 loader 图片时,就会获得

// src 为图片,trace 为loader生成的占位图
import { src, trace } from './assets/images/gakki-363kb.jpg'

// 定义图片组件为
export const img = ({ src, trace }) => {
  const img = new Image()

  img.src = trace
  img.onload = function () {
     img.src = src
  }
  
  return img
}
// 挂载在 document.body 上
document.body.appendChild(img({ src, trace }))

参考:

  • webpack book
  • webpack doc
  • 若干 npm readme

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
P3P Header解决Cookie跨域的问题
Mar 12 Javascript
纯js实现遮罩层效果原理分析
May 27 Javascript
Express作者TJ告别Node.js奔向Go
Jul 14 Javascript
JS中的数组方法笔记整理
Jul 26 Javascript
BootStrap glyphicon图标无法显示的解决方法
Sep 06 Javascript
vue自定义指令实现v-tap插件
Nov 03 Javascript
基于vue2.x的电商图片放大镜插件的使用
Jan 22 Javascript
vue实现自定义多选与单选的答题功能
Jul 05 Javascript
详解Vue一个案例引发「内容分发slot」的最全总结
Dec 02 Javascript
对vuex中getters计算过滤操作详解
Nov 06 Javascript
JavaScript实现捕获鼠标坐标
Apr 12 Javascript
Vue 实现拨打电话操作
Nov 16 Javascript
JavaScript页面倒计时功能完整示例
May 15 #Javascript
vue组件间通信六种方式(总结篇)
May 15 #Javascript
JS正则表达式封装与使用操作示例
May 15 #Javascript
微信小程序实现授权登录
May 15 #Javascript
基于vue实现一个神奇的动态按钮效果
May 15 #Javascript
微信小程序导航栏跟随滑动效果的实现代码
May 14 #Javascript
详解VSCode配置启动Vue项目
May 14 #Javascript
You might like
解析php利用正则表达式解决采集内容排版的问题
2013/06/20 PHP
简单谈谈php中的unicode和utf8编码
2015/06/10 PHP
Symfony2学习笔记之插件格式分析
2016/03/17 PHP
PHP与Java对比学习日期时间函数
2016/07/03 PHP
不使用XMLHttpRequest实现异步加载 Iframe和script
2012/10/29 Javascript
JavaScript常用全局属性与方法记录积累
2013/07/03 Javascript
JS弹出层的显示与隐藏示例代码
2013/12/27 Javascript
基于jQuery实现在线选座之高铁版
2015/08/24 Javascript
利用jquery制作滚动到指定位置触发动画
2016/03/26 Javascript
JS使用cookie设置样式的方法
2016/06/30 Javascript
JS快速实现移动端拼图游戏
2016/09/05 Javascript
Ionic + Angular.js实现图片轮播的方法示例
2017/05/21 Javascript
javascript实现Java中的Map对象功能的实例详解
2017/08/21 Javascript
JS实现的JSON数组去重算法示例
2018/04/11 Javascript
Vue 指令实现按钮级别权限管理功能
2019/04/23 Javascript
vuex actions异步修改状态的实例详解
2019/11/06 Javascript
微信小程序国际化探索实现(附源码地址)
2020/05/20 Javascript
vue实现井字棋游戏
2020/09/29 Javascript
javascript实现滚轮轮播图片
2020/12/13 Javascript
一个检测OpenSSL心脏出血漏洞的Python脚本分享
2014/04/10 Python
Python3写入文件常用方法实例分析
2015/05/22 Python
python 类对象和实例对象动态添加方法(分享)
2017/12/31 Python
TensorFlow 合并/连接数组的方法
2018/07/27 Python
Python3 单行多行万能正则匹配方法
2019/01/07 Python
python+ffmpeg批量去视频开头的方法
2019/01/09 Python
Python实现截取PDF文件中的几页代码实例
2019/03/11 Python
Pytorch to(device)用法
2020/01/08 Python
Python如何发送与接收大型数组
2020/08/07 Python
Ted Baker英国官网:男士和女士服装及配件
2017/03/13 全球购物
国际奢侈品品牌童装购物网站:Designer Childrenswear
2019/05/08 全球购物
优秀士兵先进事迹
2014/02/06 职场文书
合伙购房协议样本
2014/10/06 职场文书
南京大屠杀观后感
2015/06/02 职场文书
2015年美容师个人工作总结
2015/10/14 职场文书
大学生饮品店创业计划书范文
2019/07/10 职场文书
Python爬虫基础之爬虫的分类知识总结
2021/05/13 Python