最近部署了个新的博客主题,并花了些时间来做前端优化,在这过程中有不少收获,也遇到不少问题。现就部分笔者比较感兴趣的点拿出来记录一下。
笔者没有相关知识和技能,主要是按照 YSlow 和 Google PageSpeed 所建议的做,有些项是比较容易出问题的。
减少请求次数
通常的做法是将同类资源合并。例如将多个 JavaScript 脚本合并,将多个 CSS 文件合并,将每个图标一个图片的形式改为 CSS sprites(单个图片,基于背景定位及分割)。
减少 HTTP 传输数据量
A) 启用 HTTP 压缩(Gzip)。B) 压缩(Minify) JavaScript 和 CSS 文件。
正确设置外部资源引入顺序
将 CSS 放在 HTML 的头部,将 JavaScript 放在 HTML 的底部。CSS 用于渲染页面,需要放在前面。而 JavaScript 会阻塞式加载,应该放在最后。
充分利用浏览器缓存
给静态资源加上比较长的过期时间和缓存有效期。设置 ETags(通常 Apache 会自动设置)。
使用 cookie-free 域
静态资源通常都不需要发送和设置 cookie 信息,所以应该使用一个单独的域来做 cookie-free domain。
使用 CDN(Content Delivery Network)
A) 整个站点使用 CDN。这需要较高的成本。
B) 仅公共资源使用 CDN。这是比较通常的做法,可以非常好的利用浏览器缓存,并能分散服务器压力。比如多个网站都使用了 Google CDN 提交的 jQuery.js 时,浏览器仅在第一次访问第一个站点时下载该文件,访问其它站点时,可直接从缓存中获取。
目前有这样一些提供公共资源的CDN:
减少 DNS 查询
使用 Cookie-free 域和使用公共资源 CDN 都会增加整个网站要访问的域的数量,同时也增加了 DNS 查询数,一个 DNS 查询通常需要 20 到 120 毫秒的时间,在 DNS 查询期间浏览器无法下载任何数据。所以 YSlow 建议一个页面的使用的域不要超过 4 个。
较少 DOM 对象数量
保持比较简单的 HTML 结构,减少标签嵌套层次,这样可以增加页面渲染速度。对于负责页面来说优化该项比较有效果,但需要较高的设计水平。
以上优化建议其实需要辩证统一的,因为有些是有矛盾的,笔者就曾主要纠结于与公共资源相关的部分:
笔者最终将 jQuery,Bootstrap 脚本压缩合并到网站的脚本中了,主要是考虑到使用 Google Hosted 的 jQuery 会偶尔抽风。
以下是笔者优化时的 Apache 配置
<IfModule mod_mime.c>
# Text
AddType text/css .css
AddType application/x-javascript .js
AddType text/html .html .htm
AddType text/richtext .rtf .rtx
AddType text/plain .txt
AddType text/xml .xml
# Image
AddType image/gif .gif
AddType image/x-icon .ico
AddType image/jpeg .jpg .jpeg .jpe
AddType image/png .png
AddType image/svg+xml .svg .svgz
# Video
AddType video/asf .asf .asx .wax .wmv .wmx
AddType video/avi .avi
AddType video/quicktime .mov .qt
AddType video/mp4 .mp4 .m4v
AddType video/mpeg .mpeg .mpg .mpe
# PDF
AddType application/pdf .pdf
# Flash
AddType application/x-shockwave-flash .swf
# Font
AddType application/x-font-ttf .ttf .ttc
AddType application/vnd.ms-fontobject .eot
AddType application/x-font-otf .otf
AddType application/font-woff .woff
# Audio
AddType audio/mpeg .mp3 .m4a
AddType audio/ogg .ogg
AddType audio/wav .wav
AddType audio/wma .wma
# Zip/Tar
AddType application/x-tar .tar
AddType application/x-gzip .gz .gzip
AddType application/zip .zip
</IfModule>
<IfModule mod_expires.c>
ExpiresActive On
# Text
ExpiresByType text/css A31536000
ExpiresByType application/x-javascript A31536000
ExpiresByType text/html A3600
ExpiresByType text/richtext A3600
ExpiresByType text/plain A3600
ExpiresByType text/xml A3600
# Image
ExpiresByType image/gif A31536000
ExpiresByType image/x-icon A31536000
ExpiresByType image/jpeg A31536000
ExpiresByType image/png A31536000
ExpiresByType image/svg+xml A31536000
# Video
ExpiresByType video/asf A31536000
ExpiresByType video/avi A31536000
ExpiresByType video/quicktime A31536000
ExpiresByType video/mp4 A31536000
ExpiresByType video/mpeg A31536000
# PDF
ExpiresByType application/pdf A31536000
# Flash
ExpiresByType application/x-shockwave-flash A31536000
# Font
ExpiresByType application/x-font-ttf A31536000
ExpiresByType application/vnd.ms-fontobject A31536000
ExpiresByType application/x-font-otf A31536000
ExpiresByType application/font-woff A31536000
# Audio
ExpiresByType audio/mpeg A31536000
ExpiresByType audio/ogg A31536000
ExpiresByType audio/wav A31536000
ExpiresByType audio/wma A31536000
# Zip/Tar
ExpiresByType application/x-tar A31536000
ExpiresByType application/x-gzip A31536000
ExpiresByType application/zip A31536000
</IfModule>
<FilesMatch "\.(?i:css|js|htm|html|rtf|rtx|txt|xml|gif|ico|jpg|jpeg|jpe|png|svg|svgz|asf|asx|wax|wmv|wmx|avi|mov|qt|mp4|m4v|mpeg|mpg|mpe|pdf|swf|ttf|ttc|eot|otf|woff|mp3|m4a|ogg|wav|wma|tar|gz|gzip|zip)$">
<IfModule mod_headers.c>
Header set Pragma "public"
Header append Cache-Control "public, must-revalidate, proxy-revalidate"
Header unset ETag
</IfModule>
</FilesMatch>
<FilesMatch "\.(?i:css|js|gif|ico|jpg|jpeg|jpe|png|pdf|swf|ttf|ttc|eot|otf|woff)$">
<IfModule mod_headers.c>
Header unset Set-Cookie
</IfModule>
</FilesMatch>
<FilesMatch "\.(?i:ttf|ttc|eot|otf|woff)$">
<IfModule mod_headers.c>
Header set access-control-allow-origin "SOMEDOMAIN or *"
</IfModule>
</FilesMatch>
<IfModule mod_deflate.c>
SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|iso|tar|bz2|sit|rar)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|jpg|ico|png)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.pdf$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.flv$ no-gzip dont-vary
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
Header append Vary User-Agent env=!dont-vary
</IfModule>
如上一篇文章提到的,Web Fonts 似乎越来越流行了,而且不仅仅用做字体,还有个主要的用途就是图标。将字体用作图标有很多便利,比如可以随意调整大小而不会失真(因为字体是矢量的),可以随意设置颜色等。当前博客的部分图标就是基于自定义字体的。
说道自定义字体,不得不说说 IcoMoon App 这个超牛的工具。通过这个工具,你可以在线选择你需要的图标,然后生成 CSS Sprites 的图片或者生成 Web Fonts 下载,下载包中已经包含了定义好的 CSS 和实例 HTML 文件。此外,你还可以上传自己的 SVG 或者其它图片文件, IcoMoon App 会自动转成 CSS Sprites 或者 Web Fonts。
上面的这个图标,实质上是一个字符,就是通过 Web Fonts 定义的。
<i class="opoo-opooorg" style="font-size:36px;color:blue;"></i>
| Source |
|