需求

背景:内容发布系统(想象一下今日头条的文章)面向移动端的文章,被要求使用思源宋体的字(客户付钱买的字体),2个字体文件加起来有30MB。

PS:中文字体发展落后英文字体,最大的一个原因就是字体包太大,第二原因是字太多,所以设计字体的人也少。。。不像英文26个字母,两者不是一个量级的。

方案说明

需要技术: js, nodejs,服务器 一个,nginx

示例地址: 点我预览

github仓库:https://github.com/font-size/node-fontmin-project

核心:通过fontmin切割字体,一个原本十几MB(思源宋体)的字体通过切割基本可以达到几十KB的效果。

方案优势:

  • 整套方案由纯js实现,轻量级应用
  • 字体文件变成按需加载,量级从MB变成KB,切割后的大小不如一张普通的图
  • 对现有项目的页面改动小,对各种类型的项目兼容性好
  • 可以批量实现

实现步骤:

  1. 在服务端新增nodejs接口
  2. 前端页面新增请求post接口,根据返回的字体文件url,动态设置font-face等页面样式
  3. 示例如下



可以看到这个字体的size只有短短19.4kb,更令人惊喜的是,他是用接口实现的,也就是说,前端项目可以很方便的兼容。

从0开始架设node服务的步骤

  • 起nodejs服务,开发一个js页面
  1. 下载nodejs安装包,在服务器上(或本地)安装
  2. 新建一个目录,输入npm init,然后一路确认,生成package.json。
  3. 接着npm安装依赖 (fontmin,express,body-parser3个依赖包),代码分别是npm i fontmin --save,npm i express–save,npm i body-parser–save
  4. 开发逻辑代码(开发一个post接口)
  • nodejs代码

目录下新建express.js

// const fs = require('fs');
const fontmin = require('./fontmin')// 切割程序,后续会讲
const express = require('express');
const bodyParser = require('body-parser');
// 设置可用字体
const fonts = [{font: 'SourceHanSerifCN-Medium', name: '思源宋体'},{font: 'PangMenZhengDao', name: '庞门正道粗书体'},{font: 'RuiziGongfangMeiheiGBK', name: '锐字工房云字库美黑GBK'},{font: 'RuiziZhenyanti', name: '锐字真言体'},{font: 'YousheBiaotihei', name: '优设标题黑'},{font: 'Zihun116', name: '字魂116号-凤鸣手书'}
]// express 实例
const app = express();// 转化参数设置
app.use(bodyParser.json());app.use(bodyParser.urlencoded({extended:true
}));// post 接口
app.post('/getfontmin', function(request, response){const params = request.bodyconst font = params.fontconst text = params.text// 如果传递的font字体在后台没有就返回400const item = fonts.find(e => e.font === font)if(item) {fontmin(font, text, function(e) {if(e === 'done') {const data = {params: params,headers: request.headers} console.log(data )// 拼接参数 返回请求let back = {url: '/fontmin/font/' + font + '.ttf',font: font}response.send(back);} });} else {response.status(400);response.send('没有请求的字体文件');}
});app.listen(3000);

上述代码内容是用express监听了3000端口,定义了一个getfontmin的post接口,并在response的body返回url和font。

express.js里的getfontmin接口,接受2个参数,分别是文章中的所有文字所需要的字体类型

例:前端传的参数为

{text: '爱的飞行日志',font: 'SourceHanSerifCN-Medium'
}

获取到参数后,把这2个参数传递给定义好的fontmin 函数,切割程序。

下面是切割程序代码 fontmin.js,用到了fontmin这个npm包

module.exports = function (font, text, callback) {const Fontmin = require('fontmin')var srcPath = `./fonts/${font}.ttf`; // 字体源文件var destPath = './font';    // 输出路径var text = text || '';// 初始化var fontmin = new Fontmin().src(srcPath)               // 输入配置.use(Fontmin.glyph({        // 字型提取插件text: text              // 所需文字})).use(Fontmin.ttf2eot())     // eot 转换插件.use(Fontmin.ttf2woff())    // woff 转换插件     .use(Fontmin.ttf2svg())     // svg 转换插件.use(Fontmin.css())         // css 生成插件.dest(destPath);            // 输出配置// 执行fontmin.run(function (err, files, stream) {if (err) {                  // 异常捕捉console.error(err);}// console.log('done');        // 成功return callback('done')});
}

接受text和font作为参数,进行字体切割,可以设置对应文件和输出目录,很好很强大。

  • 注意:这里destPath设置为固定路径,在实际项目上一般需要根据页面把切割好的字体文件放到特殊目录。
  • 如前端页面是http://www.wangzhan.com/content/20200901/index.jhtml,设置destPath为/content/20200901/font 相信会是一个更好的选择。

在目录下运行node express.js

  • 到此为止,服务端里nodejs代码已经全部结束,接下来做前端实现

前端页面实现

比如我有个页面,需要压缩字体。

  • 首先开发一个post.js
function fontmin(selectDom, fontDom) {// 获取文字const text = document.querySelector(selectDom).innerText// 字体const font = fontDom// 设置post typeaxios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';// 接口地址axios.post('/getfontmin', {text: text,font: font}).then(function (response) {// 当接口成功返回时,动态给head设置csslet styleDom = document.createElement('style');styleDom.type = 'text/css';const cssText = `@font-face {font-family: "${response.data.font}";src: url("${response.data.url}") format("truetype");}p, h1 {font-family: "${response.data.font}";}`styleDom.appendChild(document.createTextNode(cssText));document.getElementsByTagName('head')[0].appendChild(styleDom)// alert("设置成功")}).catch(function (error) {console.log(error);alert("设置失败")});
}

这段js代码用了axios插件来请求post接口。这个接口即我们之前定的getfontmin接口。

根据接口返回的url和font,用js在页面上加上一个style元素,设置font-face等样式。

  • 前端页面 index.html
<!DOCTYPE html>
<html lang="en" >
<head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no,viewport-fit=cover"/>
<style>
h1 {font-size: 60px;
}
p, h1 {text-align: center;font-size: 40px;
}
</style>
</head>
<body><div id="text"><h1>爱的飞行日志</h1><p>赤道的边境</p><p>万里无云 天很清</p><p>爱你的事情</p><p>说了千遍 有回音</p><p>岸边的丘陵</p><p>崎岖不平 浪入侵</p><p>我却很专心</p><p>分辨得出 你的声音</p></div>
<script src="./js/axios.min.js"></script>
<!-- 封装了post请求的js -->
<script src="./js/post.js"></script>
<script>
// 第一个参数是文字所在dom,如id为text的div
// 第二个参数是所需的字体,如SourceHanSerifCN-Medium
fontmin('#text', "SourceHanSerifCN-Medium")
</script>
</body>
</html>

只要在页面里引用我们之前写的post.js,然后运行我们定义的fontmin()方法。

然后呢?试一下! 字体文件从13.8MB变成了19.0KB

项目总结

  1. 后台:起一个nodejs,开发一个post接口,随调随用
  2. 前端: 页面上post请求
  3. 注意浏览器跨域问题

贴张项目完整文件目录图(这是本地测试时的项目目截图,js文件夹和index.html为前端页面及资源,express.js和fontmin.js为nodejs代码,fonts是源字体文件,font为切割字体后的文件目录)

关于配置代理

  • 本地调试

方案1:通过nginx在本地做代理。

主要是把index.html(前端文件)放入nginx下的html目录中。

然后可以访问到127.0.0.1:端口/目录/index.html。

nodejs相关文件放哪里都行,只要运行起来就ok

配置代理,在conf文件,80端口上加上这段配置

location /getfontmin {proxy_pass http://127.0.0.1:3000/getfontmin;
}location /fontmin/ {root html;
}

好了,在浏览器打开http://127.0.0.1/fontmin/index.html


方案2:nginx在服务端做允许跨域配置。
这个不多说,网上文章一大堆

  • 服务端配置

方案1:还是起nginx服务。

线上环境一样配置反向代理即可。

以接口请求的方式,解决移动端页面中字体文件过大的问题相关推荐

  1. css如何设置x轴为滚动,解决移动端页面出现 X轴横向滚动条问题

    最近在用 Bootstrap 写一个需要适配 WEB 和 WAP 的网站,写完后发现 WAP 端总是会出现横向滚动条,也就是 X 轴滚动条,导致 WAP 端页面左右滑来滑去,很是令人蛋疼,即使设置了 ...

  2. php json转数组后并在前端展示,0516-如何从服务器端获取JSON格式字符串并解决到前端页面中显示...

    一. 如何从服务器端获取JSON格式字符串并解决到前端页面中显示 1.采用AJAX异步方式从服务器请求必须为字符串的数据:例如 $PHP=  '{"aaa":"bbb&q ...

  3. 解决Arcgis10.2.2中dbf文件用EXCEL打开乱码问题

    解决Arcgis10.2.2中dbf文件用EXCEL打开乱码问题 参考文章: (1)解决Arcgis10.2.2中dbf文件用EXCEL打开乱码问题 (2)https://www.cnblogs.co ...

  4. C++57个入门知识点_50 菱形继承与虚继承(C++中语法允许多重继承造成菱形继承;会造成近亲结婚的问题;可以通过虚继承的方式解决;实际项目中不多用多重继承)

    上篇C++57个入门知识点_49 多重继承与组合(一个类同时具有多个类的属性的方法:多重继承或者组合:多重继承:一个类同时继承多个类:多重继承构造和析构的顺序与普通继承类似:组合:类中包含多个成员对象 ...

  5. 解决移动端项目中苹果ios和安卓android手机点击输入框网页页面自动放大缩小

    一.需求问题 在公司的项目开发中,我们经常需要开发移动端的项目.但是,在移动端中,点击输入框的时候,网页页面会自动放大或者缩小.这个也并不是我们所想要的,我们只需要向输入框中输入内容就可以了. 二.需 ...

  6. 如何禁止视频在手机移动端页面中全屏播放

    最近公司的项目中出了需要在局部播放视频的需求,我们都知道HTML5中有一个专门的标签video用来嵌入视频.不过,这个video标签有很多的属性可能很多同学并不是很熟悉,下面我们来认识一下: 在网页里 ...

  7. 【loadrunner】解决将某个脚本中.c文件移植到其他脚本文件中,无法执行,且报Error -- Unresolved symbol错误问题

    解决将某个脚本中XFZ_C2C_FBSP.c文件移植到其他脚本文件中,无法执行,报Error -- Unresolved symbol错误问题 步骤1:将XFZ_C2C_FBSP.c文件先copy至运 ...

  8. 【已解决】WPS/OFFICE中word文件可以打印,excel打印后无响应

    问题 WPS/OFFICE中word文件可以打印,excel打印后无响应 博主用的是办公室同事共享的HP打印机,在使用过程中出现了WORD文件可以打印,但是EXCEL文件打印无反应,查看打印作业进程也 ...

  9. c语言中以追加只写方式打开文本文件,C语言中打开文件读取,写入的操作

    #include#includeint main(){ //打开文件并以读取的方式 FILE* file = fopen("E://1.txt","rt"); ...

  10. 移动端页面中阻止视频全屏播放

    最近公司的项目中出了需要在局部播放视频的需求,我们都知道HTML5中有一个专门的标签video用来嵌入视频.不过,这个video标签有很多的属性可能很多同学并不是很熟悉,下面我们来认识一下: 在网页里 ...

最新文章

  1. lucene,基于QueryParser的搜索
  2. zookeeper集群配置与配置文件详解
  3. 如何找到设备的guid_如何禁止win10自动更新显卡驱动
  4. Linux Shell脚本编程 --sort命令
  5. 【STM32】系统配置控制器相关函数和类型
  6. setTimeout(), nextTick(),setImmediate()区别 ZT~
  7. 一、设计模式 - UML (统一建模语言) - 类图
  8. vue axios封装及使用
  9. .Net FW上线报错:The OwinStartup attribute discovered in assembly ‘AppName‘.
  10. BP神经网络回归预测模型(python实现)
  11. 软件测试公司常见的部门有哪些?
  12. vosk实时语音识别
  13. php微信手机端上传图片,手机Wap微信端上传单图和上传多图的DEMO
  14. 用python抠图方便还是ps方便_我会Python之后都不屑用PS了,Python抠图太方便了!...
  15. python图片修改过、有原图、怎么得到改动的地方_Python-根据照片信息获取用户详细信息(微信发原图或泄露位置信息)...
  16. 数据库设计:需求分析
  17. 电脑网络被别的计算机控制,电脑被别人远程控制了,怎么办?
  18. 上海应届生落户政策计算机水平,2019年上海应届生落户的加分细则,上海的同学们必看!...
  19. OCR应用:证件识别
  20. PIM-SM原理(ASM)

热门文章

  1. C语言经典笔试题解析,原来微软笔试题也有简单的,C语言学习专题
  2. spoonwep破解方式使用心得
  3. python循环结构高一信息技术_高一信息技术For循环语句公开课【2019原创资源大赛】...
  4. 单片机c语言实验报告心得,关于单片机实训心得体会
  5. python热身教程_[转载]技术教程-MayaPython教程二之Python
  6. QT学习之基础Day1(自用)
  7. ffmpeg多种码率控制方式的实现
  8. java 字符替换_java string中的替换字符串
  9. 基于tensorflow的RNN中文自动写诗程序
  10. 游戏外挂篇:如何Dump内存获得游戏的辅助