浅谈 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 相关文章推荐
从新浪弄下来的全屏广告代码 与使用说明
Mar 15 Javascript
出现“不能执行已释放的Script代码”错误的原因及解决办法
Aug 29 Javascript
jquery实现的让超出显示范围外的导航自动固定屏幕最顶上
Sep 22 Javascript
jQuery数据显示插件整合实现代码
Oct 24 Javascript
在JavaScript中操作时间之getYear()方法的使用教程
Jun 11 Javascript
JavaScript Ajax实现异步通信
Dec 14 Javascript
jQuery实现的checkbox级联选择下拉菜单效果示例
Dec 26 Javascript
利用JS判断客户端类型你应该知道的四种方法
Dec 22 Javascript
vue中手机号,邮箱正则验证以及60s发送验证码的实例
Mar 16 Javascript
js+css实现打字效果
Jun 24 Javascript
vue遍历对象中的数组取值示例
Nov 07 Javascript
vue项目中使用vue-layer弹框插件的方法
Mar 11 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/07/01 PHP
php导出word格式数据的代码实例
2013/11/25 PHP
PHP实现的简单日历类
2014/11/29 PHP
详解yii2使用多个数据库的案例
2017/06/16 PHP
PHP编译configure时常见错误的总结
2017/08/17 PHP
PHP基于递归算法解决兔子生兔子问题
2018/05/11 PHP
用javascript实现画板的代码
2007/09/05 Javascript
非常棒的10款jQuery 幻灯片插件
2011/06/14 Javascript
jQuery+css实现图片滚动效果(附源码)
2013/03/18 Javascript
22点关于jquery性能优化的建议
2014/05/28 Javascript
JavaScript中用字面量创建对象介绍
2014/12/31 Javascript
NodeJS使用jQuery选择器操作DOM
2015/02/13 NodeJs
JS数组操作(数组增加、删除、翻转、转字符串、取索引、截取(切片)slice、剪接splice、数组合并)
2016/05/20 Javascript
浅谈JavaScript 数据属性和访问器属性
2016/09/01 Javascript
Javascript中构造函数要注意的一些坑
2017/01/23 Javascript
vue.js的提示组件
2017/03/02 Javascript
vue.js移动数组位置,同时更新视图的方法
2018/03/08 Javascript
Vue CLI3基础学习之pages构建多页应用
2019/06/02 Javascript
JS扁平化输出数组的2种方法解析
2019/09/17 Javascript
在vue+element ui框架里实现lodash的debounce防抖
2019/11/13 Javascript
[36:17]DOTA2上海特级锦标赛 - VGL音乐会全集
2016/03/06 DOTA
python连接sql server乱码的解决方法
2013/01/28 Python
Python Web框架Flask中使用新浪SAE云存储实例
2015/02/08 Python
Pythont特殊语法filter,map,reduce,apply使用方法
2016/02/27 Python
Python实现向服务器请求压缩数据及解压缩数据的方法示例
2017/06/09 Python
Python正确重载运算符的方法示例详解
2017/08/27 Python
python实现贪吃蛇游戏
2020/03/21 Python
python适合人工智能的理由和优势
2019/06/28 Python
Python 解决火狐浏览器不弹出下载框直接下载的问题
2020/03/09 Python
Python HTTP下载文件并显示下载进度条功能的实现
2020/04/02 Python
牦牛毛户外探险服装:Kora
2019/02/08 全球购物
酒店员工职业生涯规划
2014/02/25 职场文书
2014年资料员工作总结
2014/11/18 职场文书
《雪域豹影》读后感:父爱的伟大
2019/12/23 职场文书
再次探讨go实现无限 buffer 的 channel方法
2021/06/13 Golang
vue-treeselect的基本用法以及解决点击无法出现拉下菜单
2022/04/30 Vue.js