浅谈 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 相关文章推荐
JQuery打造PHP的AJAX表单提交实例
Nov 03 Javascript
jquery1.5.1中根据元素ID获取元素对象的代码
Apr 02 Javascript
25个非常棒的jQuery滑块插件和教程小结
Sep 02 Javascript
js报$ is not a function 的问题的解决方法
Jan 20 Javascript
DIV始终居中的js代码
Feb 17 Javascript
jQuery插件实现文字无缝向上滚动效果代码
Feb 25 Javascript
利用AngularJs实现京东首页轮播图效果
Sep 08 Javascript
JSON对象 详解及实例代码
Oct 18 Javascript
原生JS简单实现ajax的方法示例
Nov 29 Javascript
jQuery实现的鼠标拖动浮层功能示例【拖动div等任何标签】
Dec 29 jQuery
小程序自定义单页面、全局导航栏的实现代码
Mar 15 Javascript
layer.open弹层查看缩略图的原图,自适应大小的实例
Sep 05 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中把数据库查询结果输出为json格式简单实例
2015/04/09 PHP
再推荐十款免费的php开发工具
2015/11/09 PHP
php把时间戳转换成多少时间之前函数的实例
2016/11/16 PHP
浅谈PHP中pack、unpack的详细用法
2018/03/12 PHP
jQuery 选择器、DOM操作、事件、动画
2010/11/25 Javascript
关于window.pageYOffset和document.documentElement.scrollTop
2011/04/05 Javascript
从数据结构分析看:用for each...in 比 for...in 要快些
2013/04/17 Javascript
jquery实现按Enter键触发事件示例
2013/09/10 Javascript
jQuery获取checkboxlist的value值的方法
2015/09/27 Javascript
微信小程序 实例应用(记账)详解
2016/09/28 Javascript
jQuery多选框选择数量限制方法
2017/02/08 Javascript
jQuery中实现text()的方法
2019/04/04 jQuery
Vue v-for中的 input 或 select的值发生改变时触发事件操作
2020/08/31 Javascript
小程序实现tab标签页
2020/11/16 Javascript
[01:36:17]DOTA2-DPC中国联赛 正赛 Ehome vs iG BO3 第一场 1月31日
2021/03/11 DOTA
写了个监控nginx进程的Python脚本
2012/05/10 Python
python中文乱码的解决方法
2013/11/04 Python
python中as用法实例分析
2015/04/30 Python
对PyTorch torch.stack的实例讲解
2018/07/30 Python
python实现维吉尼亚加密法
2019/03/20 Python
python3安装crypto出错及解决方法
2019/07/30 Python
python2和python3应该学哪个(python3.6与python3.7的选择)
2019/10/01 Python
Python3变量与基本数据类型用法实例分析
2020/02/14 Python
使用Tensorflow-GPU禁用GPU设置(CPU与GPU速度对比)
2020/06/30 Python
python爬虫要用到的库总结
2020/07/28 Python
Python中logging日志记录到文件及自动分割的操作代码
2020/08/05 Python
Zatchels官网:英国剑桥包品牌
2021/01/12 全球购物
值传递还是引用传递
2015/02/08 面试题
外贸业务员的岗位职责
2013/11/23 职场文书
参观考察邀请函范文
2014/01/29 职场文书
导购员的岗位职责
2014/02/08 职场文书
科研课题实施方案
2014/03/18 职场文书
给小学生的新年寄语
2014/04/04 职场文书
大学生自我评价200字(4篇)
2014/09/17 职场文书
2015年个人招商工作总结
2015/04/25 职场文书
小学数学教学随笔
2015/08/14 职场文书