webpack的fontmin解决方案

前端开发中,经常需要引入中文字体库,但由于中文的字体文件文件太大,需要进行裁剪才能用于线上环境。

另外,随着现在字体图标的普及,许多glyphicons的字体文件,也需要裁剪才能发布到线上。

裁剪字体文件的常用方式是使用fontmin,通过传入一个字符串,把字体文件裁剪成只包含这个字符串里字符的文件。通常的做法是,在发布之前,使用fontmin工具处理一下字体文件,并生成最终需要的文件。

随着gulp、webpack等前端工程化构建工具的普及,我们需要在构建项目时引入fontmin,在构建过程中输出裁剪后的字体文件。gulp的fontmin工具:gulp-fontmin

使用webpack进行项目构建时,有两种方式可以引入fontmin。

一种是使用loader,在加载ttf、woff、svg等字体格式文件时,使用特定的loader加载文件,传入一个字符串并输出裁剪结果。笔者在搜索时只发现了一个哥们两年前写的fontmin-loader,但是无法使用,于是自己动手写了一个:awesome-fontmin-loader,使用方式如下:

{
  test: /\.(svg|woff|woff2|ttf|eot)$/,
  use: [
    {
      loader: 'awesome-fontmin-loader',
      options: {
        limit: 1000,
        name: 'assets/fonts/[name].[hash].[ext]',
        text: '天地玄黄宇宙洪荒' // 使用到的字符
      }
    }
  ]
}

其中text是项目中使用到的字符组成的字符串,使用awesome-fontmin-loader加载的字体文件,只会包含text中的字符。

另一种方式是使用webpack plugin,当前可用的方案是fontmin-webpack,这个plugin是用来收集css中的glyphicons字符并裁剪字体文件的,也可以用于汉字字体文件的裁剪,使用方式是传入一个字符数组:

new FontminPlugin({
  autodetect: false,
  glyphs: fontCharactors // 字符数组
})

 

解决了裁剪字体文件的问题,还有一个问题是如何获取要传入loader或者plugin的字符串或字符数组。

如果你的网页中使用到的文本都集中维护在一个或几个文件里,获取这些文本中的字符会简单些。笔者遇到的情况是网页的文本都分散在各个目录中的html/ts/json等文件里,所以需要扫描这些代码文件提取出字符。

扫描工作一般需要遍历文件夹,取出每个文件中的字符,然后去重,这样会生成一个网页显示文字的字符集的超集,因为代码中的字符、注释中的字符等不需要的字符也都被加了进来,但尽管如此,字符的数目还是会远小于字体文件中的字符总数,因此可以用来有效裁剪字体文件。

这个扫描的小程序被封装成了一个node module,如果你需要使用它,请访问:charactor-scanner,这个module会输出一个函数,接收文件夹路径等参数并输出一个字符数组。

const Scan = require('charactor-scanner');

Scan({
  dir: [path.resolve(__dirname, './test-directory')]
}, data => console.log("Async Callback call: ", data.join()));


// Async Callback call: {,|,},~,?,?,ノ,ン,リ,ピ,ー,ト,的,方,式,来,和,会,计,师,费

Scan({
  dir: path.resolve(__dirname, './test-directory')
}).then(data => console.log("Async Promise call: ", data.join()));

// Async Promise call:  !,",#,$,方,式,来,和,会,计,师,费,?,?,ノ,ン,リ,ピ,ー,ト

console.log("Sync call: ", Scan({
  dir: path.resolve(__dirname, './test-directory'),
  sync: true,
  appendAscii: false
}).join());

// Sync call:  {,",a,:,?,?,,,b,ノ,ン,リ,ピ,ー,ト,},c,o,n,s,l,e,.,g

扫描文件夹一般是一个异步操作,如何在webpack配置中引入异步操作呢?

webpack 2.x已经支持config文件返回一个promise对象,因此可以把webpack.config.js写成类似下面这样:


const scan = require('charactor-scanner');

module.exports = function () {
  return scan({
    dir: [helpers.root('src')],
    ext: ['html', 'css', 'ts', 'json', 'js']
  }).then(fontCharactors => webpackMerge(commonConfig, {
    module: {
      rules: [
        {
          test: /\.(svg|woff|woff2|ttf|eot)$/,
          use: [
            {
              loader: 'awesome-fontmin-loader',
              options: {
                limit: 1000,
                name: 'assets/fonts/[name].[hash].[ext]',
                text: fontCharactors.join('')
              }
            }
          ]
        }
      ]
    }
  }))
};

这样,就可以在webpack构建的时候,扫描代码文件并裁剪字体文件了。

转载于:https://my.oschina.net/JackSparrow/blog/865004

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值