浅谈 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团购倒计时特效实现方法
May 07 Javascript
JQuery+Ajax实现数据查询、排序和分页功能
Sep 27 Javascript
JS获取子窗口中返回的数据实现方法
May 28 Javascript
Bootstrap学习笔记之css样式设计(1)
Jun 07 Javascript
浅析jQuery Ajax通用js封装
Jun 22 Javascript
Bootstrap编写一个同时适用于PC、平板、手机的登陆页面
Jun 30 Javascript
JS中substring与substr的用法
Nov 16 Javascript
BootStrap Select清除选中的状态恢复默认状态
Jun 20 Javascript
vue2实现可复用的轮播图carousel组件详解
Nov 27 Javascript
使用vue-router完成简单导航功能【推荐】
Jun 28 Javascript
深入浅析var,let,const的异同点
Aug 07 Javascript
Vue this.$router.push(参数)实现页面跳转操作
Sep 09 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命令行使用方法和命令行参数说明
2014/04/08 PHP
php实现的支持断点续传的文件下载类
2014/09/23 PHP
PHP接口并发测试的方法(推荐)
2016/12/15 PHP
PHP bin2hex()函数基础实例讲解
2019/02/11 PHP
23个Javascript弹出窗口特效整理
2011/02/25 Javascript
javascript提取URL的搜索字符串中的参数(自定义函数实现)
2013/01/22 Javascript
javaScript中的this示例学习详解及工作原理
2014/01/13 Javascript
JS+CSS实现电子商务网站导航模板效果代码
2015/09/10 Javascript
JS实现横向与竖向两个选项卡Tab联动的方法
2015/09/27 Javascript
详解JavaScript的变量和数据类型
2015/11/27 Javascript
Angular2实现自定义双向绑定属性
2017/03/22 Javascript
详解nodejs的express如何自动生成项目框架
2017/07/12 NodeJs
关于Vue在ie10下空白页的debug小结
2018/05/02 Javascript
jQuery实现简易聊天框
2020/02/08 jQuery
vue实现广告栏上下滚动效果
2020/11/26 Vue.js
python中的代码编码格式转换问题
2015/06/10 Python
在Python中移动目录结构的方法
2016/01/31 Python
Python探索之静态方法和类方法的区别详解
2017/10/27 Python
Python DataFrame设置/更改列表字段/元素类型的方法
2018/06/09 Python
详解Python循环作用域与闭包
2019/03/21 Python
关于Python3 类方法、静态方法新解
2019/08/30 Python
Pandas操作CSV文件的读写实现方法
2019/11/13 Python
详解Java中一维、二维数组在内存中的结构
2021/02/11 Python
意大利高端时尚买手店:Stefania Mode
2018/03/01 全球购物
乌克兰第一的珠宝网上商店:Gold.ua
2019/11/29 全球购物
Oracle中delete,truncate和drop的区别
2016/05/05 面试题
好军嫂事迹材料
2014/01/15 职场文书
大学毕业自我鉴定范文
2014/02/03 职场文书
双语教学实施方案
2014/03/23 职场文书
个人总结格式范文
2015/03/09 职场文书
幼儿园教师心得体会范文
2016/01/21 职场文书
2016年教育局“我们的节日——端午节”主题活动总结
2016/04/01 职场文书
导游词之宿迁乾隆行宫
2019/10/15 职场文书
JavaScript分页组件使用方法详解
2021/07/26 Javascript
《杜鹃的婚约》OP主题曲「凸凹」无字幕影像公开
2022/04/08 日漫
vue递归实现树形组件
2022/07/15 Vue.js