Web fonts and extension for Azure App Service
在前端开发中,图标(Icon)是一种必不可少的资源文件。从最开始的png小图,到CSS Sprites,再到近些年的Font Awesome这类的图标字体文件,搭建一个简洁大方的网站越来越容易。
我的博客
使用
Hexo
框架,搭配
Next
主题,整体效果我也比较满意。但当我将其托管到Azure Website上时,却发现了两个404错误,提示找不到Font Awesome的两个字体文件。
我们抛开这个错误,先来说说字体文件以及计算机系统是如何显示字符的。
图标字体文件
首先介绍一款软件——
FontForge
,这是一个开源的字体编辑器。我们从Windows系统的字体文件夹(
C:\Windows\Fonts\
)中随便找出一款中文字体,如微软雅黑,用
FontForge
打开,点击
CJK
区域的任意一个汉字,你会发现每个汉字其实就是一个矢量图形,整个字体文件就是一个以
Unicode
为索引的图形表,Uicode值就是每个字符的编号。类似的,其它字符如英文字母、希腊字母也都是一个矢量图形。这也是这些字符放大后
不会
变得模糊的原因。
现在的字体文件通常是TTF(TrueType fonts)字体,例如我们上图所示的微软雅黑字体,它所表示的字库也叫做
矢量字库
。与矢量字库对应的就是点阵字库
了,它们的区别是早期没有图形接口的DOS系统、某些Linux终端或者一些嵌入式系统只能渲染点阵字体(Raster fonts,也称为光栅字体、位图字体),而且点阵字体放大后会变得模糊。
当我们知道字体文件就是一个图形库的索引表时,就能大致理解计算机系统是如何显示字符的了。首先我们的字符是存储在文件中,而负责处理文字的软件(Word、Notepad等)都会显式或隐式的使用一种编码方案来存储这些字符,例如ANSI、UTF-8、Unicode、GBK等等。然后当计算机系统要显式这些字符的时候,会读取这些编码值,结合当前使用的字体文件,使用这些编码值就可以在字体文件中找到对应的图形,最终这些图形通过显卡输出到图形显示器上。这也就解释了为什么当文件的编码方案设置错误时,就会出现乱码。
既然我们用到的各种字符(汉字、英文字母、阿拉伯数字等等)本质上是一个图形,为啥不把网站设计中常用的图标也放到字体文件中呢?于是 Font Awesome 、 iconfont 这之类的专门用于网页设计的图标字体应运而生。与此同时你会发现,当把图标看成是普通的文本后,font-size、color之类的文本修饰也能随手解决,再加上CSS3的支持,还能添加阴影、旋转等效果。
使用字体文件中的图标
在网页中使用
Font Awesome
中的图标,只需要以下两个步骤:
-
引入CSS文件
1
<link href="/lib/font-awesome/css/font-awesome.min.css" rel="stylesheet">
-
在
<i>
或<span>
中引入相关的class,例如:1
2
3<i class="fa fa-home"></i>
<i class="fa fa-home" style="font-size:48px;"></i>
<i class="fa fa-home" style="font-size:60px;color:red;"></i>
你不禁要问,这是如何办到的呢?答案就在
Font Awesome
提供的CSS里面。
1 |
@font-face { |
首先你会看到一个@font-face的声明,其中font-family属性定义了这个字体的名称,src属性定义了渲染该字体需要下载的字体文件。定义两个src以及一堆url是为了浏览器兼容性的需要,format属性告诉浏览器这个字体的格式,可选的字体格式有 woff、woff2、truetype、opentype、embedded-opentype、svg等。不同的 浏览器支持 不同的字体格式。
然后,在class fa中引用了这个字体,并且定义了一些基本属性。
1 |
.fa { |
最后,对于每一个图标,定义了一个class,例如:
1 |
.fa-home:before { |
这里,使用
:before
在DOM中增加了一个
伪元素
,使用反斜杠
\
表示一个16进制数字,这个数字就是该图标在字体文件中的编码,也就是它的索引位置。
伪类(
Pseudo-classes
,使用一个冒号:
)与伪元素(Pseudo-elements
,使用两个冒号::
)是不一样的。但由于历史及CSS版本的原因,大多数浏览器同时支持用一个冒号:
或两个冒号::
来实现伪元素。
MIME Types
说完了字体和
Font Awesome
,回到我们要解决的这个问题上来。Chrome的开发者工具报了两个404错误,提示下面两个文件找不到。
Azure App Service 现在支持 运行在 Linux系统中 ,因此背后的Web服务器就不是IIS了。我在创建App Service的时候,选择的是Windows系统,因此背后的Web服务器是IIS。
![]()
使用web.config
最显而易见的方式是配置web.config来让IIS支持这两种文件类型。
1 |
<configuration> |
使用Site Extension
Azure Site Extension是App Service提供的一种平台接口,允许开发者或网站运营者对网站的
运行环境
做一些定制化和扩展。它的实现机制是使用
XDT Transforms
来修改
ApplicationHost.config
。
ApplicationHost.config
是IIS7以上版本中的IIS配置文件,它包含了当前机器上所有的网站、应用程序、虚拟目录、应用程序池以及一些全局的服务器配置。我们平时使用的web.config,其实就是覆盖了这个文件中的部分配置信息。当然有一些重要的配置信息是无法被覆盖的。
使用
XDT Transforms
来配置MIME Types也比较简单:
1 |
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> |
将上面的xml文件保存为
applicationhost.xdt
,打开App Service对应的scm站点,将这个文件上传到
SiteExtensions
目录下,重启App Service,改动就生效了。
如果你想把这个Site Extension分享给其他人,你需要将其打包成一个NuGet包,然后将其上传到Azure官方的托管平台上。具体步骤可以参考这篇文章: Writing a Site Extension for Azure Websites 。
完整的代码在这里: https://github.com/johnnyqian/enable-font-awesome-site-extension
Site Extensions的托管
Site Extensions最开始的时候是托管在
https://www.siteextensions.net
上的。2018年2月份的时候,
官方宣布
将Site Extensions的托管迁移到
https://www.nuget.org
。原因是
siteextensions.net
是个低流量的网站,不值得投入大量的运维成本,因此将其合并到
nuget.org
。
熟悉.NET的同学应该对
NuGet
不陌生,它是.NET生态系统中的包管理工具。类似的工具有很多,比如Java中的Maven,Node中的npm等。
nuget.org
是托管NuGet包的一个在线网站,它已经成为.NET生态系统一个重要的组成部分,甚至.NET中的一些BCL类库也通过
nuget.org
来发布,而不是跟随.NET Framework。
Site Extension的包发布到
nuget.org
后,如何与其它常规的NuGet包区分开呢?答案是需要在nuspec中添加如下的改动:
1 |
<tags>AzureSiteExtension</tags> |
我的这个FontAwesome的Site Extension在这两个托管平台都可以找到:
- https://www.siteextensions.net/packages/EnableFontAwesome/
- https://www.nuget.org/packages/EnableFontAwesome
在Azure Portal中,选择一个App Service,找到Extensions这个选项卡,点击添加,找到需要的Extension就可以了。
其它常用的Site Extensions
1. HTTP to HTTPs
对于启用了全站HTTPS的网站来说,这个extension就是必须的了。当用户输入的是HTTP的URL时,这个extension会将URL重定向到以HTTPS开头。在添加Extensions的页面查找
Redirect HTTP to HTTPS
可以找到这个extension。代码在这里:
https://github.com/gregjhogan/redirect-http-to-https-site-extension
你也可以打开App Service对应的scm站点,搜索和安装extensions。
![]()
2. No-WWW
网站URL中的WWW前缀其实是一个历史问题,到底要不要带WWW前缀,是个有争议的问题。很多流行的站点已经不在其主站的URL中加上WWW前缀了,例如
Twitter
,
Stack Overflow
等。但是这个概念已经是根深蒂固了,许多人在输入URL的时候会输入WWW,因此我们需要将其重定向到不带WWW的域名地址(
Bare Domain
)。作为一个博客网站,我倾向于使用不带WWW前缀的URL。在添加Extensions的页面查找
Remove www domain prefix
可以找到这个extension。代码在这里:
https://github.com/jamesharling/No-WWW
与此相反的是,很多大型的商业公司,例如
Google
,
Microsoft
,
QQ
等,它们的主站都是带WWW前缀的。当用户没有键入WWW前缀时,网站会将访问链接重定位到带WWW前缀的URL。目前
nuget.org
上还没有人创建这样的extension,如果你有兴趣,可以尝试着创建它并将其上传到
nuget.org
上。
不光是网站URL中的WWW有争议,连URL中http(s)之后的两道斜杠(
Forward Slashes
)都是多余的。“万维网之父”——蒂姆·伯纳斯-李(Tim Berners-Lee)坦言,当初设计时留下些许遗憾。例如,万维网的网址须以http(s)://
打头,伯纳斯-李认为,两道斜杠增加了用户的字符输入量( Berners-Lee ‘sorry’ for slashes ),其实并没有必要。