页面加载性能之WebP在项目中的应用

项目中的静态图片,一般有两种使用方式:

  • HTML中的 标签
  • CSS中的 background-image 属性

尽可能的使用CSS的方式去加载图片,当然如果你依赖图片本身的宽高等比缩放的特性,还是使HTML的方式。

框架

本文将以vue-cli 3.0脚手架搭建的项目为例。

转换工具

我们选择的是 Imagemin,版本选择6.1.0,因为7.0.0之后的版本在windows上有兼容性问题,目前还未修复。

npm install [email protected] --save-dev
npm install imagemin-webp --save-dev

转换脚本

我们的转换脚本需要支持全量转换,单个目录转换,以及单文件转换三种模式,质量默认选择75,实际测下来发现,75的质量跟100的质量肉眼基本看不出来区别,以下是脚本代码的实现:

/**
 * 脚本位于tools目录,即 ./tools/webp.js
 * 项目的源码均位于src目录,即 ./src/
 * 可以自行调整代码中的部分目录配置
 */
const imageMin = require('imagemin')
const imageMinWebp = require('imagemin-webp')
const path = require('path')
const fs = require('fs')

let quality = 75
let rootDir = path.join(__dirname, '../src')

async function init (dir) {
  console.log('start!')
  await loop(dir)
  console.log('completed!')
}

async function loop (dir) {
  let res = fs.readdirSync(dir, {
    withFileTypes: true
  })
  await imageMin([path.join(dir, '*.{jpg,png}')], dir, {
    plugins: [
      imageMinWebp({
        quality: quality
      })
    ]
  })
  console.log(dir)
  for (let i = 0, length = res.length; i < length; i++) {
    if (res[i].isDirectory()) {
      await loop(path.join(dir, res[i].name))
    }
  }
}

if (process.argv.length >= 3) {
  if (process.argv[3]) {
    quality = process.argv[3]
  }
  let dir = path.join(__dirname, '../', process.argv[2])
  const stats = fs.statSync(dir)
  if (stats.isDirectory()) {
    rootDir = dir
    init(rootDir)
  } else if (stats.isFile()) {
    console.log('start!')
    imageMin([dir], path.dirname(dir), {
      plugins: [
        imageMinWebp({
          quality: quality
        })
      ]
    })
    console.log(dir)
    console.log('completed!')
  }
} else {
  init(rootDir)
}

转换全部图片:

node ./tools/webp.js

转换 src/components 目录下的全部图片:

node ./tools/webp.js src/components

转换单个图片文件 src/images/picture.png:

node ./tools/webp.js src/images/picture.png

转换全部图片,并设置转换质量为100:

node ./tools/webp.js src 100

检测是否支持

https://modernizr.com/downloa...

打开上面的链接,点BUILD,即可下载

有以下两种引入方式:

  • Es6 Module: 通过import引入
  • Inline Push(内联脚本): 通过将代码放在 标签中引入

Es6 Module

适合纯前端渲染的架构,如Vue,React,Angular等。这种架构在JS执行之前,页面上没有图片内容,所以不用考虑 FOUC (Flash of Unstyled Content) 的情况。

Inline Push(内联脚本)

适合后端渲染的架构,如PHP,Nodejs等。这种架构下,页面上可能已经有了图片,所以必须将 Inline Script 放在 中,并且位于所有