Xlenco

Xlenco

github
zhihu
email

前端字體壓縮方案

Fontmin#

Fontmin 是一個純 JS 字體子集化方案。利用 Fontmin 可以提取 TTF 字體文件中需要用到的字符,然後轉換為 TTF 文件輸出,從而實現 “壓縮” 的效果
官網地址:ecomfe.github.io/fontmin/

安裝 Fontmin#

npm install --save fontmin

創建個 font.js 文件

名字可以隨意,主要是等會運行用

var Fontmin = require("fontmin")

var fontmin = new Fontmin()
  .src("./src/assets/font/example.ttf")
  .dest("./src/assets/fontmin/")
  .use(
    Fontmin.glyph({
      text: "這裡寫你要壓縮的文字"
    })
  )

fontmin.run(function(err, files) {
  if (err) {
    throw err
  }
})

這是 fontmin 文檔上的用法,還有其他用法可以去看看 GitHub 上的文檔:fontmin
然後用 node 執行一下命令:

shell
複製代碼node .\font.js

進階#

上述方案如果遇到大量的文字壓縮的需求是很麻煩的,實際項目中我們也不可能手動把所有文字都寫出來放到 ${text} 中去。接下來搞一下讀取文件的功能,讀取其中包含的所有字符。

const fs = require("fs")

fs.readFile("./idenx.html", (err, data) => {
  if (err) {
    console.log(err)
  }
  const mySet = new Set(data.toString()) // 去重的目的
  console.log(Array.from(mySet).join(""))
})

完整代碼#

以下源碼來自:zhuanlan.zhihu.com/p/48318293

const fs = require("fs")
const Fontmin = require("fontmin") // 需要借助 fontmin 插件
let set = new Set()

//get all possible characters
const scanFolder = (dir, done) => {
  let results = []
  fs.readdir(dir, (err, list) => {
    if (err) {
      return done(err)
    }
    let i = 0
    ;(function iter() {
      // 這裡的立即函數觸發了閉包,使results的值一直保存
      let file = list[i++]
      if (!file) {
        // iterator遍歷,file不存在即為執行完成狀態
        return done(null, results)
      }
      file = dir + "/" + file
      fs.stat(file, (err, stat) => {
        if (stat && stat.isDirectory()) {
          scanFolder(file, (err, res) => {
            // 重新調用方法,獲取子目錄下的目錄結構
            results = results.concat(res)
            iter()
          })
        } else {
          results.push(file)
          iter() // 執行下一步
        }
      })
    })()
  })
}

//get all possible characters
const generateFinalHTML = finalString => {
  const fontmin = new Fontmin()
    .src("./src/assets/font/SourceHanSansCN-Regular.ttf") // 源字體文件路徑
    .dest("./src/assets/font/fontmin/") // 壓縮後文件存放路徑,最終使用的是這個壓縮後的文件
    .use(
      Fontmin.glyph({
        text: finalString, // 也可以直接指定需要生成的字符集
        hinting: false
      })
    )

  fontmin.run(err => {
    if (err) {
      throw err
    }
  })
}

//get all possible characters
// 指定掃描路徑,注意路徑不同,會導致最終掃描到的字符數不同
scanFolder("src/views", (n, results) => {
  results.forEach(file => {
    const result = fs.readFileSync(file, "utf8")
    const currentSet = new Set(result)
    // 獲取到每個文件中的字符,並存儲到set集中
    set = new Set([...set, ...currentSet])
  })
  generateFinalHTML(Array.from(set).join(""))
  console.log("共生成:" + Array.from(set).length + "個字符")
})

後言#

如果你的需求量不大也可以用客戶端
app.png
客戶端下載:
網盤:https://www.123pan.com/s/IlX7jv-GSJk3.html
官網(Github): https://github.com/ecomfe/fontmin-app/releases/download/v0.2.0/Fontmin-v0.2.0-win64.zip

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。