首頁 > 軟體

gulp-font-spider實現中文字型包壓縮實踐

2023-03-17 06:05:16

1.背景

在前端開發中,經常需要使用特定的字型包,但由於中文字型包特別大,嚴重影響網頁的載入速度,所以需要對字型包進行壓縮。

2.方法

提取專案中使用到的漢字,並利用gulp-font-spider來實現ttf格式字型包的壓縮,並生成eot,svg,woff等其他格式的字型包,其中使用gulp來實現這一流程的自動化。

3.gulp-font-spider 安裝及使用

字蛛是一箇中文 WebFont 自動化壓縮工具,它能自動分析頁面使用的 WebFont 並進行按需壓縮,無需手工設定。

3.1 特性

  • 按需壓縮:從原字型中剔除沒有用到的字元,可以將數 MB 大小的中文字型壓縮成幾十 KB
  • 簡單可靠:完全基於 HTML 與 CSS 分析進行本地處理,無需 js 與伺服器端輔助
  • 自動轉碼:將字型轉碼成所有瀏覽器支援的格式,包括老舊的 IE6 與現代瀏覽器
  • 圖示字型:除了常規的字型支援外,還支援圖示字型(字蛛 v1.0.0 新特性)

3.2 安裝

npm install gulp-font-spider --save-dev

3.2 使用範例

var gulp = require( 'gulp' );
var fontSpider = require( 'gulp-font-spider' );
gulp.task('fontspider', function() {
    return gulp.src('./index.html')
        .pipe(fontSpider());
});
gulp.task('defualt', ['fontspider']);

推薦的跨瀏覽器 @font-faceCSS 寫法:

/* html中 宣告 WebFont*/
@font-face {
  font-family: 'pinghei';
  src: url('../font/pinghei.eot');
  src: 
    url('../font/pinghei.eot?#font-spider') format('embedded-opentype'),
    url('../font/pinghei.woff') format('woff'),
    url('../font/pinghei.ttf') format('truetype'),
    url('../font/pinghei.svg') format('svg');
  font-weight: normal;
  font-style: normal;
}
/*使用選擇器指定字型*/
.home h2, .demo > .test {
    font-family: 'pinghei';
}

特別說明: @font-face中的 src定義的 .ttf 檔案必須存在,其餘的格式將由工具自動生成

font-spider [options] <htmlFile1 htmlFile2 ...>

3.3 使用場景限制

  • 僅支援固定的文字與樣式,不支援 javascript 動態插入的元素與樣式
  • .otf 字型需要轉換成 .ttf 才能被壓縮
  • 僅支援 utf-8 編碼的 HTML 與 CSS 檔案
  • CSS content 屬性只支援普通文字,不支援屬性、計數器等特性

4. 自動化流程主要步驟

4.1.提取專案中使用到的漢字

利用through2外掛,將業務資料夾src內所有的漢字提取出來,並生成chars.txt檔案暫存。

gulp.task('extract', () => {
    return gulp.src('src/**/*{.vue,.scss,.ts}', { dot: true }).pipe(concat('chars.txt'))
        .pipe(through2.obj(function (file, enc, callback) {
            const { contents } = file;
            let text = contents.toString();
            var result = text.match(/[u4e00-u9fa5]/ig)?.join('');
            if (result){
                file.contents = Buffer.from(result)
                this.push(file);
            }
            callback();
        })).pipe(gulp.dest('fontMinify/'))
});

4.2 生成字蛛所需的html入口檔案

讀取上一步生成的chars.txt中的漢字,組裝html檔案,寫入字型檔案引入樣式,並將提取出的漢字插入html中

gulp.task('insertCharactersToHtml', () => {
    return gulp.src('fontminify/chars.txt').pipe(concat('fontMin.html'))
        .pipe(through2.obj(function (file, enc, callback) {
            const { contents } = file;
            let text = contents.toString();
            if (text){
                file.contents = Buffer.from(`<!DOCTYPE html>
                    <html lang="en">
                    <head>
                        <meta charset="UTF-8">
                        <style>
                            @font-face {
                                font-family: 'fz';
                                src: url('${fontName}.eot');
                                src: url('${fontName}.eot?#font-spider') format('embedded-opentype'),
                                    url('${fontName}.woff') format('woff'),
                                    url('${fontName}.ttf') format('truetype'),
                                    url('${fontName}.svg') format('svg');
                                font-weight: normal;
                                font-style: normal;
                            }
                            /*使用選擇器指定字型*/
                            #app {
                                font-family: 'fz';
                            }
                        </style>
                    </head>
                    <body>
                        <div id="app">
                        ${text}
                        </div>
                    </body>
                    </html>`);
                this.push(file);
            }
            callback();
        })).pipe(gulp.dest('fontMinify'))
});

4.3 利用字蛛執行壓縮任務

gulp.task('fontspider', function () {
    return gulp.src('./fontMinify/fontMin.html')
        .pipe(fontSpider());
});

5. 完整程式碼及目錄

5.1 目錄結構

5.2 完整程式碼

實現提取文字,壓縮字型包後,移動到靜態資原始檔夾public下並刪除任務中生成的fontMInify檔案

const gulp = require('gulp')
const through2 = require("through2");
const del = require('del');
const concat = require('gulp-concat');
const fontSpider = require('gulp-font-spider');
let fontName = 'FZMWFont'
gulp.task('genFontMinify', () => {
    return gulp.src(`public/originalFont/${fontName}.ttf`).pipe(gulp.dest('fontMinify/'))
});
// 提取專案中的漢字
gulp.task('extract', () => {
    return gulp.src('src/**/*{.vue,.scss,.ts}', { dot: true }).pipe(concat('chars.txt'))
        .pipe(through2.obj(function (file, enc, callback) {
            const { contents } = file;
            let text = contents.toString();
            var result = text.match(/[u4e00-u9fa5]/ig)?.join('');
            if (result){
                file.contents = Buffer.from(result)
                this.push(file);
            }
            callback();
        })).pipe(gulp.dest('fontMinify/'))
});
// 將提取出的漢字插入模版html中
gulp.task('insertCharactersToHtml', () => {
    return gulp.src('fontminify/chars.txt').pipe(concat('fontMin.html'))
        .pipe(through2.obj(function (file, enc, callback) {
            const { contents } = file;
            let text = contents.toString();
            if (text){
                file.contents = Buffer.from(`<!DOCTYPE html>
                    <html lang="en">
                    <head>
                        <meta charset="UTF-8">
                        <style>
                            @font-face {
                                font-family: 'fz';
                                src: url('${fontName}.eot');
                                src: url('${fontName}.eot?#font-spider') format('embedded-opentype'),
                                    url('${fontName}.woff') format('woff'),
                                    url('${fontName}.ttf') format('truetype'),
                                    url('${fontName}.svg') format('svg');
                                font-weight: normal;
                                font-style: normal;
                            }
                            #app {
                                font-family: 'fz';
                            }
                        </style>
                    </head>
                    <body>
                        <div id="app">
                        ${text}
                        </div>
                    </body>
                    </html>`);
                this.push(file);
            }
            callback();
        })).pipe(gulp.dest('fontMinify'))
});
// 字型檔案壓縮
gulp.task('fontspider', function () {
    return gulp.src('./fontMinify/fontMin.html')
        .pipe(fontSpider());
});
// 將生成後的字型檔案移動到預定的靜態資源目錄
gulp.task('mvMinifyFontToPublic', function () {
    return gulp.src(`./fontMinify/${fontName}.*`)
        .pipe(gulp.dest('public/fonts'));
});
// 刪除字型壓縮檔案產生的中間檔案
gulp.task('rmFontMinify', function () {
    return del('fontMinify')
});
gulp.task('default', gulp.series('genFontMinify','extract', 'insertCharactersToHtml', 'fontspider', 'mvMinifyFontToPublic','rmFontMinify'))

6.優缺點

6.1 優點

如上介紹,可以實現字型檔案的壓縮並生成多種格式字型包,本文使用的字型包從5M壓縮到了200K,體積大大減小,並且可以通過gulp.watch監聽src資料夾的變動來實現這一流程的自動化

6.2 缺點

目前gulp-font-spider只能實現提取專案中出現的漢字,對於後端介面返回的動態漢字無法提取,只能預先列舉可能使用的漢字來使用

以上就是gulp-font-spider實現中文字型包壓縮實踐的詳細內容,更多關於gulp font spider中文字型包壓縮的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com