浅谈 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 相关文章推荐
JavaScript 数组详解
Oct 10 Javascript
js 事件截取enter按键页面提交事件示例代码
Mar 04 Javascript
JavaScript判断textarea值是否为空并给出相应提示
Sep 04 Javascript
Javascript学习笔记之数组的构造函数
Nov 23 Javascript
js实现鼠标经过表格行变色的方法
May 12 Javascript
基于jQuery实现的菜单切换效果
Oct 16 Javascript
jQuery验证插件validate使用方法详解
Sep 13 Javascript
JS小数转换为整数的方法分析
Jan 07 Javascript
微信小程序request请求后台接口php的实例详解
Sep 20 Javascript
原生JS+HTML5实现跟随鼠标一起流动的粒子动画效果
May 03 Javascript
深入浅出理解JavaScript闭包的功能与用法
Aug 01 Javascript
解决mui框架中switch开关通过js控制开或者关状态时小圆点不动的问题
Sep 03 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中一个控制字符串输出的函数
2006/10/09 PHP
php printf输出格式使用说明
2010/12/05 PHP
php防攻击代码升级版
2010/12/29 PHP
yii操作session实例简介
2014/07/31 PHP
thinkPHP模型初始化实例分析
2015/12/03 PHP
php设计模式之原型模式分析【星际争霸游戏案例】
2020/03/23 PHP
JS URL传中文参数引发的乱码问题
2009/09/02 Javascript
JavaScript插入动态样式实现代码
2012/02/22 Javascript
jquery图片放大功能简单实现
2013/08/01 Javascript
Vue数据驱动模拟实现5
2017/01/13 Javascript
详解vue-validator(vue验证器)
2017/01/16 Javascript
详解如何在React组件“外”使用父组件的Props
2018/01/12 Javascript
NodeJS实现同步的方法
2019/03/02 NodeJs
微信小程序新手教程之页面打开数量限制
2019/03/03 Javascript
详解express使用vue-router的history踩坑
2019/06/05 Javascript
vue从零实现一个消息通知组件的方法详解
2020/03/16 Javascript
jQuery实现html可联动的百分比进度条
2020/03/26 jQuery
详解vue-flickity的fullScreen功能实现
2020/04/07 Javascript
js实现弹窗效果
2020/08/09 Javascript
如何利用vue实现波谱拟合详解
2020/11/05 Javascript
vue在图片上传的时候压缩图片
2020/11/18 Vue.js
uni-app 自定义底部导航栏的实现
2020/12/11 Javascript
[55:48]VGJ.S vs TNC Supermajor 败者组 BO3 第二场 6.6
2018/06/07 DOTA
[01:10:48]完美世界DOTA2联赛PWL S2 GXR vs PXG 第一场 11.18
2020/11/18 DOTA
pandas-resample按时间聚合实例
2019/12/27 Python
python各层级目录下import方法代码实例
2020/01/20 Python
Django2.1.7 查询数据返回json格式的实现
2020/12/29 Python
用HTML5制作数字时钟的教程
2015/05/11 HTML / CSS
AmazeUI 缩略图的实现示例
2020/08/18 HTML / CSS
银行类自荐信
2014/02/04 职场文书
集体婚礼策划方案
2014/02/22 职场文书
小学生运动会通讯稿
2014/09/23 职场文书
毕业论文致谢部分怎么写
2015/05/14 职场文书
电影建党伟业观后感
2015/06/01 职场文书
springcloud整合seata
2022/05/20 Java/Android
python运行脚本文件的三种方法实例
2022/06/25 Python