在进行包巨细优化工作时,紧缩图片的巨细是其间一个重要的环节。而要紧缩的图片包括本地项目中的图片和之后要新增到项目中的图片。所以紧缩图片分为两个部分:

  1. 遍历项目中的一切图片,紧缩后替换原图片
  2. 每次git提交代码前,假如有新增图片,进行紧缩后再提交

紧缩本地项目中的图片

require "fileutils"
require "find"
require "tinify"
t = Time.now
$image_count = 0
$total_size = 0
$total_after_size = 0
$fail_count = 0
$success_count = 0
$success_file_name = "successLog.txt"
$fail_file_name = "failLog.txt"
compress_dir = "/Users/zhouweijie1/Documents/test/Expression.xcassets" #即将紧缩的文件夹途径放这
# 获取白名单列表途径
$white_list_path = "#{Dir.pwd}/gitHooks/imageCompressWhiteList.txt"
$keys = ['tbfVHxRmxxR3Vb3XQwrxMbfHPNnxszpH', 'B83mGyQcbpmFzz1Qym5ZdhT3Ss503b5b', 'L1DfbF8kpRzstlMfbvmkvCSg6knkQD71', '2L6km1p5yJRZsNYs0GJ6m4klL1rMJ4RJ', '5wmc8dDxY1WKg4DTPSLXQ20dWWjRbzyG', '1DkYWCXDvPJfMrNbV6NPB0QpQTGzZLfD', 'bRG9yXbc07w77sP43gqjgP8tlgDPjdVJ', 'xwvXrTp2pSJYWDjkHQ7wTBTxDMbLdx4r', '4pFYmxVBK6vnpKR5hh8r0hD4BGmS75K4', '6rSpQHxHpygLyZMQnTH6WNjxGVV9mt0x']
$keys_index = -1
def setup_key
    $keys_index += 1
    Tinify.key = $keys[$keys_index]
    Tinify.validate! # validate后会更新compression_count
    if $keys_index == $keys.length
        puts "本月一切免费运用次数都用完,请增加key"
    elsif Tinify.compression_count >= 500
        setup_key
    end
end
def write_log(fail, success)
    if success != 0
        file = File.new($success_file_name, "a")
        file.syswrite("#{success}\n")
    end
    if fail != 0
        file = File.new($fail_file_name, "a")
        file.syswrite("#{fail}\n")
    end
end
def compress(image_name)
    begin
        # Use the Tinify API client.
        origin_size = File.size(image_name)
        Tinify.from_file(image_name).to_file(image_name)
        log = image_name + "\n#{origin_size} bit" + " -> " + "#{File.size(image_name)} bit"
        puts log + ":#{Time.now}"
        write_log(0, log)
        $success_count += 1
    rescue Tinify::AccountError
        # Verify your API key and account limit.
        setup_key
        print("失效的key:" + Tinify.key + "\n")
        compress(image_name)
    rescue Tinify::ClientError => e
        # Check your source image and request options.
        log = image_name + "\nClientError:#{e.message}"
        puts log + ":#{Date.now}"
        write_log(log, 0)
        $fail_count += 1
    rescue Tinify::ServerError => e
        # Temporary issue with the Tinify API.
        log = image_name + "\nServerError:#{e.message}"
        puts log + ":#{Date.now}"
        write_log(log, 0)
        $fail_count += 1
    rescue Tinify::ConnectionError => e
        # A network connection error occurred.
        log = image_name + "\nConnectionError:#{e.message}"
        puts log + ":#{Date.now}"
        write_log(log, 0)
        $fail_count += 1
    rescue => e
        # Something else went wrong, unrelated to the Tinify API.
        log = image_name + "\nOtherError:#{e.message}"
        puts log + ":#{Time.now}"
        write_log(log, 0)
        $fail_count += 1
    end
end
# 检测到文件夹中一切PNG和JPEG图片并紧缩
def traverse_dir(file_path)
    setup_key
    Dir.glob(%W[#{file_path}/**/*.png #{file_path}/**/*.jpeg]).each do |image_name|
        $total_size += File.size(image_name)
        # compress(image_name)
        $total_after_size += File.size(image_name)
        $image_count += 1
    end
end
traverse_dir(compress_dir)
time = "时间:#{Time.now - t}s from #{t} to #{Time.now}"
count = "图片总数:#{$image_count},本次紧缩图片数:#{$image_count}, 成功图片数:#{$success_count},失利图片数:#{$fail_count}"
size = "之前总巨细:#{$total_size/1024.0} k,之后总巨细:#{$total_after_size/1024.0} k,优化巨细:#{($total_size - $total_after_size)/1024.0}"
puts time
puts count
puts size
write_log(0, time)
write_log(0, count)
write_log(0, size)
complete = "紧缩完毕!!!"
if $fail_count != 0
    complete += "有#{$fail_count}张图片失利,请查看:#{File.absolute_path($fail_file_name)}"
end
puts complete
# 查看key的免费运用次数
def check_keys_status
    $keys.each do |key|
        begin
            Tinify.key = key
            Tinify.validate!
            puts "#{key}:#{Tinify.compression_count}"
        rescue
        end
    end
end
# 白名单
def ignore?
    file = File.new($white_list_path, "a+")
    file.readlines.each { |line|
        line_without_white_space = line.strip
        if line_without_white_space.length > 0
            result = $image_path.match?(line_without_white_space)
            if result
                return true
            end
        end
    }
    return false
end

紧缩即将提交的图片

要紧缩即将提交的图片,就要运用git hook阻拦代码提交动作,将pre-commit文件放到.git/hooks文件中就行了。pre-commit文件中的代码逻辑为获取当时提交的内容,遍历是否是图片,是的话就履行紧缩脚本:

#!/bin/sh

#检测是否为开始提交
if git rev-parse --verify HEAD >/dev/null 2>&1
then
    against=HEAD
else
    # Initial commit: diff against an empty tree object
    against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

# If you want to allow non-ASCII filenames set this variable to true.
git config hooks.allownonascii true

# Redirect output to stderr.
exec 1>&2

#获取.git地点目录
git_path=$(cd "$(dirname "$0")";cd ..;cd ..; pwd)
#获取当时分支名
branch=$(git symbolic-ref --short HEAD)

# 得到修改过的代码的文件列表
git diff --cached --name-only --diff-filter=ACMR -z $against | while read -d $'\0' f; do
if [[ $f == *".png" || $f == *".jpg" || $f == *".jpeg" ]];then
    #拼接文件绝对途径
    path="$(cd "$(dirname "$0")";cd ..;cd ..; pwd)/$f"
    pattern='/Pods/'
    pathStr="$path"
  if [[ ! ($pathStr =~ $pattern) ]]; then
    #履行紧缩脚本
    ruby "$git_path/gitHooks/imageCompressor.rb" $path $branch
    git add $f
  fi
fi
done

紧缩脚本单独放在一个文件中,内容如下:

require "tinify"
$keys = %w[tbfVHxRmxxR3Vb3XQwrxMbfHPNnxszpH B83mGyQcbpmFzz1Qym5ZdhT3Ss503b5b L1DfbF8kpRzstlMfbvmkvCSg6knkQD71 2L6km1p5yJRZsNYs0GJ6m4klL1rMJ4RJ 5wmc8dDxY1WKg4DTPSLXQ20dWWjRbzyG 1DkYWCXDvPJfMrNbV6NPB0QpQTGzZLfD bRG9yXbc07w77sP43gqjgP8tlgDPjdVJ xwvXrTp2pSJYWDjkHQ7wTBTxDMbLdx4r 4pFYmxVBK6vnpKR5hh8r0hD4BGmS75K4 6rSpQHxHpygLyZMQnTH6WNjxGVV9mt0x]
$keys_index = -1
$image_path = ARGV[0]
$branch_name = ARGV[1]
# 获取.git地点目录
git_path = `git rev-parse --git-dir`; git_path = git_path.strip;
# 获取当时文件地点目录
cur_path = `printf $(cd '#{git_path}'; cd ..; pwd)/gitHooks`; cur_path = cur_path.strip;
$white_list_path = "#{cur_path}/imageCompressWhiteList.txt"
def setup_key
    $keys_index += 1
    Tinify.key = $keys[$keys_index]
    Tinify.validate! # validate后会更新compression_count
    if $keys_index == $keys.length
        puts "本月一切免费运用次数都用完,请增加key"
    elsif Tinify.compression_count >= 500
        setup_key
    end
end
def ignore?
    file = File.new($white_list_path, "a+")
    file.readlines.each { |line|
        line_without_white_space = line.strip
        if line_without_white_space.length > 0
            result = $image_path.match?(line_without_white_space)
            if result
                return true
            end
        end
    }
    return false
end
begin
    # Use the Tinify API client.
    result = ignore?
    if result
        puts "图片在白名单中,不紧缩:" + $image_path
    else
        setup_key
        Tinify.from_file($image_path).to_file($image_path)
        puts "图片紧缩成功:" + $image_path
    end
rescue Tinify::AccountError
    # Verify your API key and account limit.
    setup_key
rescue Tinify::ClientError => e
    # Check your source image and request options.
    puts "图片紧缩失利:" + $image_path + ", ClientError:#{e.message}"
rescue Tinify::ServerError => e
    # Temporary issue with the Tinify API.
    puts "图片紧缩失利:" + $image_path + ", ServerError:#{e.message}"
rescue Tinify::ConnectionError => e
    # A network connection error occurred.
    puts "图片紧缩失利:" + $image_path + ", ConnectionError:#{e.message}"
rescue => e
    # Something else went wrong, unrelated to the Tinify API.
    puts "图片紧缩失利:" + $image_path + ", OtherError:#{e.message}"
end

假如某张图片不需要或许不能紧缩,需要将图片名放到白名单中,白名单格式如下:

test_expression_100fen@3x.png
test_expression_666@3x.png
expression_100fen@3x.png

上面说到将pre-commit文件放到.git/hooks文件中就可以完成提交阻拦,也可以用脚本完成这个操作: 文件名:setupGitHook.rb

#!/usr/bin/ruby
require "Fileutils"
# 获取.git地点目录
git_path = `git rev-parse --git-dir`; git_path = git_path.strip;
# 获取当时文件地点目录
cur_path = `printf $(cd '#{git_path}'; cd ..; pwd)/gitHooks`; cur_path = cur_path.strip;
puts "gitPath:#{git_path}"
puts "cur_path:#{cur_path}"
# .git目录下没有hooks文件夹时新建一个
if Dir.exist?("#{git_path}/hooks") == false
  FileUtils.mkpath("#{git_path}/hooks")
end
# 将当时文件夹中pre-commit文件拷贝到.git/hooks目录下
FileUtils.cp("#{cur_path}/pre-commit", "#{git_path}/hooks/pre-commit")

当搭档很多时,比如有四十多个,让每个人都在项目目录下履行一遍setupGitHook.rb,每个搭档都来问一遍就比较麻烦了。所以可以添加一个运转脚本,运转项目时自动履行就可以了:

# Type a script or drag a script file from your workspace to insert its path.

# 获取gitHooks文件夹方位
gitHooks_path=$(**cd** "$(git rev-parse --git-dir)"; **cd** ..; **pwd**;)/gitHooks
ruby $gitHooks_path/setupGitHook.rb

如下图:

图片自动压缩

Demo地址:github.com/Wejua/Demos…