使用预加载提速你的网站

  • 原文:Speed Up Your Site Using Prefetching
  • 原作者:Jon Fox 译者:潜行者m
  • 版权声明:版权归原作者所有,翻译仅供学习使用,内容有修改,转载请先开启节操模式,保留上面信息。
    预加载(prefetching)这个东西很好理解。我们都知道浏览器可能会在渲染之前需要一些资源。预加载不仅仅提前告诉浏览器这个页面或者可能用到的资源,而且还通常提前保存这个资源到浏览器的缓存,这样就可以以非阻塞的方式请求、下载对应资源提高效率。

有很多方法可以实现预加载,但是这里有三种比较简单实用的方法。

DNS 预加载

DNS 是将域名转换成服务器 IP 地址的协议。DNS 的解析速度通常是非常快的一般在 100ms 以内,但是因为 DNS 解析要发生在任何对服务器的请求之前,这样会造成一个级联效应(cascade effect),这样就会增加页面加载的时间。浏览器解析页面或者 session 的时候会访问静态文件加速服务器的域名,会使用诸如 images.mydomin.com 等域名来加载静态文件。有些浏览器支持 meta 标签可以提前声明这些需要用到的静态加速服务器域名,这样浏览器就可以预先解析它们,调用资源直接通过解析后的 IP ,不需要再进行 DNS 解析。写法如下:

<link href=”//my.domain.com” rel=”dns-prefetch” />
<link href=”http://my.domain.com/“ rel=”prefetch” /> <!– IE9+ –>

增加了这个标签之后,支持它的浏览器将会提前进行域名的 DNS 解析,而不用等待请求资源的时候再去解析它。这项技术一般用在浏览者有可能去的页面,提前对页面进行 DNS 的预加载。Chrome、Firefox 和 IE9+ 支持这个功能。

即使看上去只是节省了几百毫秒而已,但是合计起来也是不少的时间。它是一种安全的优化方法同时很容易实现。我很好奇有多少网站使用了这项技术,我打开了 Alexa 排名前 100K 的网站。但是只有 552 个网站(使用率 0.55%)正确的使用了 DNS 预加载技术。这么简单的技术应该被更多的网站使用。

资源预加载

在现在的网站中,网页的大小很大程度上取决于网页中图片的大小。如果提前请求并且下载这些图片,可以有明显的提速效果。大多数情况下,网页作者知道一个图片什么时候需要加载这样就不需要提前在浏览器中声明,例如使用 ajax 或者浏览者浏览页面时触发的一些事件来加载一个图片。资源预加载就是提前让浏览器加载图片、脚本、样式或者其他资源。不仅仅用于加载图片,可以让所有类型的资源提前被缓存在浏览器的缓存中。

这项技术是最久远古老和最经常使用的,抱歉,我无法给出具体的统计数字。仍然有很多网站没有正确的使用这项技术,然而仅仅预加载几张图片就可以制造巨大的用户体验差异。

页面预加载、预渲染

页面预加载就像资源预加载,不同的是页面预加载提前加载了它本身。这项技术首先在 Firefox 浏览器中可以使用。你可以使用下面的标签来测试一下别的浏览器看看这个页面(或者相关资源)能否被提前加载:

    <link href=”/my-next-page.htm” rel=”prefetch” />

不同于预渲染,浏览器不仅仅会下载这个页面,而且还会把这个页面需要用到的资源一块下载下来。通常在内存中渲染这个页面(不会被浏览者看到)这样当请求这个页面的时候就可以很快显示在浏览者面前。预渲染最先在 chrome 中可以使用。你可以在页面中添加下面标签来实现预渲染:

    <link href=”http://mydomain.com/my-next-page.htm“ rel=”prerender” />

这项技术在目前非常有争议,在其他技术中也很有风险。预渲染的那个页面必须非常确定是浏览者即将浏览的页面。比较常见的例子是 Google 搜索,它将会预渲染页第一个返回页面。在 Alexa 排行榜前 100K 个站点中,我只发现了 95 个使用这项技术的例子。即使这项技术还不是很成熟也无法适应所有需求,但是我认为很多网站应该用一下来提升用户体验。

争议

预加载一直是有争议的话题。很多人们认为它没有效果而且在浪费宽带。而且它还用到一些不重要的客户端的资源(尤其是很多手机设备)。此外值得一提的是,预加载、预渲染页面可能会导致一些浏览者统计和访问日志记录的问题,因为系统不知道浏览者是否真正访问过这个页面还是通过预加载请求的。

总结

尽管有一些问题,但是预加载还是有很大优势的。请求的速度我们一般无法控制,所以把资源提前尽可能多的放入缓存是我们解决问题的方法。当用户在等待请求的时候,成本太高了,我们可以使用这些技术大大的提升性能。如果你还没有做这些,建议你去应用这些技术到你的网站上。结果可能不一样,所以你可以使用专业工具(例如:Torbit)来检查预加载技术帮你做了多少。

HTML5 标签 hgroup 已经被废除

HTML5 增加了很多语义化的标签,hgroup 就是其中一个,它用来表明标题的集合。如果有主标题、副标题,可以使用这个来包裹一下,一般比较常见的就是网站的标题和网站描述:网站标题和副标题常用 hgroup 包裹

但是这样做并不是太必要,而且还有一些麻烦。一般来说,很难有单纯的 hn 标题标签集合在一起,通常还包含一些其他内容,但是使用 hgroup 包裹的内容,必须是 hn 标题标签,否则不会通过 HTML5 验证。又有谁会为了这么一个增强语义性用处不大的标签专门去生成一堆 hn 标签?

然后好消息是,这个标签在最新的 HTML5.1 版中被废除了,以后可以不再用了。但是又面临了一些问题,如果我有类似这种 声明主标题和对应副标题说明 的需求,我应该怎样增强语义性?

W3 给了一些结构建议,查看原文请点击这里。下面引用原文然后用我自己的博客标题做一个例子。

用其他方法模拟 hgroup 的语义性

使用标点符号分割

最简单的方法就是使用标点符号分割主标题和副标题:

<h1>潜行者m: 关注前端开发热爱简约设计。</h1>
这种类型比较适合于文章标题,很显然不适合网站标题。 ### 使用 span 标签标注副标题说明
<h1>潜行者m
   <span>关注前端开发热爱简约设计。</span> 
</h1>
这种方式比上面好一点,但是感觉还是怪怪的,但是结构比较简单,如果不怕麻烦,推荐下面一种方法。 ### 使用 header 标签包裹标题和描述 header 也是 HTML5 新增的语义性标签,用来表示头部信息,一般不会被废弃。我们可以这样做:
<header>
<h1>潜行者m</h1>
<p>关注前端开发热爱简约设计。</p>
</header>

强烈推荐这种写法,这样保证了语义性的同时,也保证了代码的整洁。

HTML5 video 跨浏览器兼容的方法

在过去 flash 是网页上最好的解决视频的方法,截至到目前还算是主流,像那些优酷之类的视频网站、虾米那样的在线音乐网站,仍然使用 flash 来提供播放服务。但是这种状况将会随着 HTML5 的发展而改变。就视频而言,HTML5 新增了 video 来实现在线播放视频的功能。

使用 HTML5 的 video 可以很方便的使用 JavaScript 对视频内容进行控制等等,功能十分强大,同时代码比较少加快加载速度。此外跨平台性比较好,特别是一些平板、手机等。例如苹果公司的产品不支持 flash 仅支持 HTML5 中的 video 功能。

但是 HTML5 的兼容性问题是个硬伤,我们可以在网页中使用 video 来播放视频,但使用早期浏览器的访问者可能无法正常观看这个视频。此外,由于视频编码器的历史渊源导致各种浏览器支持的视频格式不同。应对这些问题,想在网页中使用 HTML5 video 功能,可以按照下面三个步骤操作。

第一步:提前准备好多格式视频文件

由于编码器的版权问题,导致不同浏览器对视频格式的兼容性不同。目前没有一个视频格式兼容所有浏览器,唯一的解决方法就是把视频转换成多种格式。

首先要准备一个 mp4 格式的视频,可以在苹果设备中使用;其次要准备 ogv 格式的视频,用在火狐浏览器中;最后要准备一下 webm 格式的视频,这个可以用在谷歌浏览器等。webm 是谷歌提出的,开源、免费,很有可能成为兼容所有浏览器的视频格式。

准备多格式浏览器的麻烦之处在于转换格式。视频转换工具国内的功能比较少,转换格式可能没有上面后两个,而且质量良莠不齐,往往需要注册才能使用。推荐一个国外的工具 Online converter ,在线免费视频转换工具。甚至不用安装软件,直接选择相应的目标格式,然后上传视频,配置一下参数就可以转换出来了。没有合适工具的朋友,可以尝试一下。

第二步:编写对应 HTML5 video 代码

HTML5 中的 video 实际上就是一个简单的标签,包含了一些视频相关信息等。下面我直接给出具体代码,然后简单解释一下:

<video width=”800” height=”374”>
<source src=”my_video.mp4” type=”video/mp4” />
<source src=”my_video.ogv” type=”video/ogg” />
<source src=”my_video.webm” type=”video/webm” />
你浏览器不支持 video 功能,点击这里下载视频: <a href=”video.webm”&gt下载视频</a&gt.
</video>

video 标签表示这里是一个视频,width、height 属性分别表示这个视频内容的宽高(单位像素)。video 标签中可以包含 source 标签,source 标签用来表示引用的视频和视频的格式、类型。为了保证向下的兼容性,我们还在 video 标签中加了一句提示,这句话在支持 video 标签的浏览器中是不会显示的,如果不支持就会显示出来。这里,还增加了一个视频的下载地址,如果浏览器不支持,可以让用户选择下载下来看。

特别需要注意一点,你的主机必须能正确的处理这事些视频请求。确保你的主机被请求这些视频的时候会在 Content-Type 头发送正确的 MIME 类型。如果你不清楚,可以咨询一下主机服务商,也可以自己添加。如果主机支持 .htaccess ,可以在 .htaccess 文件中增加下面语句:

AddType video/ogg .ogv
AddType video/mp4 .mp4
AddType video/webm .webm

大体就是这样,比较简单,更加具体的关于 video 的使用方法,可以搜索一下,也可以见本文扩展阅读链接,在这里不再赘述。

第三步:为旧版浏览器做兼容

前面说过,如果浏览器不支持 video ,将会把 video 中的提示内容显示出来。那么对付老旧浏览器,我们可以用传统的 flash 来替换这个提示内容。这样,当浏览器不兼容 video 标签的时候,就会显示出 flash 版本的视频。例如:

<video width=”800” height=”374”>
<source src=”my_video.mp4” type=”video/mp4” />
<source src=”my_video.ogv” type=”video/ogg” />

&lt;object width="800" height="374" type="application/x-shockwave-flash" data="fallback.swf"&gt;
    &lt;param name="movie" value="fallback.swf" /&gt;
    &lt;param name="flashvars" value="autostart=true&amp;amp;file=video.flv" /&gt;
&lt;/object&gt;

</video>
直接按照原来正常的 flash 引入方法写进 video 标签中即可。这样,我们就实现了跨浏览器兼容的 video 功能使用。

参考文章和扩展阅读

Blink 浏览器内核来了

之前 Web 界有一个重磅信息,那就是 Opera 抛弃了自己的内核 Presto 而改用 WebKit 内核。大家都在议论缺乏了渲染内核的多样性,会不会影响到浏览器和 Web 标准之类的进步和发展。而现在,应该不用讨论了,因为一个新内核 Blink 要来了。

Blink 是由 WebKit 内核衍生出来的,是由 Chromium 开发维护的新项目。在官方的博客上有详细的说明:Blink: A rendering engine for the Chromium project。关于这个浏览器的更加详细的特性和目标,可以看这里:http://www.chromium.org/blink。大体就是一大堆的优化,提高速度,各种支持。

之前的 WebKit 内核是由 谷歌 chrome 和 苹果 safari 共同开发,谷歌不干了,从 WebKit 中衍生分离出 Blink 不知道是何居心,不过浏览器渲染内核的多样性是肯定有了,以谷歌的技术,这种多样性应该会促进 Web 的发展。

对于国内来说,Blink 是开源引擎,X60 、X狗 之类的浏览器,又可以再增加一个核了,因为 Blink 对速度做了优化,应该会比 WebKit 还要快,所以可能会被命名为超急速三核切换功能。总之,妈妈再也不用担心我的浏览器核心不够用了。

最害怕的是增加前端工程师的压力,万戈前辈好像很蛋碎,以谷歌的技术,应该不会像对 IE 那样费力的去 Hack,至于那些前缀什么的,随着标准的确立,就自然去掉了。

Opera 怎么办?当然,它也会使用 Blink 内核的。还是让我们拭目以待吧,看看这个内核究竟怎么样。

此外,Firefox 也耐不住寂寞了,前几天也在官方博客上发表了关于联手三星共同开发下一代浏览器内核(servo)的声明(点击这里查看官方声明),这是要干什么?Web 界还是不太平啊,期待国内有哪个技术团队能开发一个自主的内核啊。

使用原生 JavaScript 在页面加载完成后处理多个函数

JavaScript 脚本语言的执行,是需要触发的。一般的做法就是在网页中,直接编写几个函数,有的在代码被加载的时候就被浏览器处理,或者使用类似下面的代码来触发实现函数的相关功能。

<div id=”link” onclick=”fun()” ></div>

上面代码的意思就是,当鼠标点击 id 为 link 的元素的时候,就触发了它的 onclick 事件,然后执行使用 JavaScript 定义的 fun 函数。这样的做法肯定是很不合理的,因为触发操作直接写进了 HTML 结构里面,内容和行为没有隔离开,对日后的二次开发或者修改带来不便。

需要注意的是,当事件处理与对应元素绑定起来的时候,只有在那个元素加载完之后才能进行操作。如果说把处理的脚本放在了 head 区域,浏览器会报错。因为下面的 HTML 元素还没有加载出来,head 中的处理脚本已经被处理了。

一个好的执行 JavaScript 代码的方法应该是 行为内容分离的在页面加载后处理 的。所以,处理 JavaScript 代码我们要用到 监听器 window 对象的 load 事件

监听器

监听器实际上的功能就是行为与内容分离的。以前需要在 HTML 中加上一些触发事件来触发 JavaScript 的相关函数,而现在直接在 JavaScript 中对某个元素的使用监听器,监听这个元素的事件,如果这个元素被触发了某些事件,在监听器中又定义了这个事件对应的处理函数,那么就会处理这个函数。

W3C 的标准方法叫做 addEventListener ,被IE9,chrome,firefox,opera所支持,写法:

window.addEventListener(‘load’,function,false);

早期 IE 中有 attachEvent 方法效果类似:

window.attachEvent(‘onload’,function);

使用监听器的方法也很简单,就是先获取页面中的某个元素,然后对这个元素使用监听器,定义监听的事件和对应的事件处理函数,就上文例子:

document.getElementById(‘link’).addEventListener(‘click’,fun,false);

关于监听器更加详细的使用说明,请见文末补充资料。

window.onload 事件

onload 事件只有在整个页面已经完全载入的时候才会被触发,我们将 JavaScript 代码写进 onload 事件中,就可以保证在 HTML 元素被加载完成之后,浏览器才会处理我们的 JavaScript 代码。基础的写法:

window.onload = function(){
//code
}

这样,这个函数里面的 code 会在加载完成之后被处理。但是,这种方法有个缺陷,就是只能用于这一个函数。页面中无法出现多个 window.onload 事件,如果出现了多个 onload 事件,那么后面的内容会覆盖前面的。

那么,我们可以这样做,在一个 window.onload 事件中,写上所有需要加载的函数名,然后在外面定义函数:

window.onload = function(){
func1();
func2();
}

function func1(){…}
function func2(){…}
这样做虽然可以,但是很不方便,因为我们需要把所有要加载的函数名都写进去,修改起来就会很麻烦。当然办法肯定是有的,jQuery 就特别提供了很强大的多脚本加载方法,那么原生的 JavaScript 肯定也有办法。

window.onload 同时处理多个函数

我们需要编写一个处理函数,先看一下代码:

    function addLoadListener(fn){
if (typeof window.addEventListener != ‘undefined’){
window.addEventListener(‘load’,fn,false);
}else if(typeof document.addEventListener != ‘undefined’){
document.addEventListener(‘load’,fn,false);
}else if (typeof window.attachEvent != ‘undefined’){
window.attachEvent(‘onload’,fn);
}else{
var oldfn = window.onload;
if(typeof window.onload != ‘function’){
window.onload = fn;
}else{
window.onload = function(){
oldfn();
fn();
};
}
}
}

简单的来解析一下,这个自定义的 addLoadListener 函数,传递一个 函数名称 作为参数。它首先判断浏览器是否支持相关的 监听器,如果支持 监听器,就使用 监听器 监听 window 对象的 onload 事件,然后处理这个函数。这段代码使用 if 语句判断了所有浏览器的监听事件,是跨浏览器兼容的。

我们把这段代码放在 JavaScript 代码段的最上面,然后在下面定义相关函数,然后使用下面语句来加载 JavaScript 函数了。

addLoadListener(func);
function func() {…}

这样,有什么 JavaScript 函数是需要在页面加载完成之后处理的,直接使用 addLoadListener 函数即可,而且可以使用多个。通常来说,所有的 JavaScript 最好都使用 onload 事件加载,以避免意外情况发生。

引用和补充资料

将 WordPress 博客从 SAE 迁出搬回 JustHost

前几天不知道为什么,SAE 老是抽风,然后打开很慢甚至无法打开,然而 ping 确实可以 ping 的通。不通过顶级域名而是直接使用 SAE 提供的二级域名也无法打开。

我一直以为 SAE 是非常正规、高质量的,可能偶尔遇到几次抽风问题,事实上这是我第一次遇到。写了一篇文章,结果等了一个下午也没有发表出去。期间,我找了一些网友进行测试,发现不是我个人网络的问题,他们也都打不开。然后 哼哼猪 跟我说,我的博客经常遇到这种很慢的情况。难道是我之前都没有怎么管理导致的吗?

我打算再等等看,第二天恢复正常了。然后第三天一大清早的,又是这种问题。我上网搜索了一下其他放在 SAE 上面的网站,没有这个问题。我开始忍受不了了,忍受不了这种影响用户体验的问题存在。于是打算从 SAE 迁出去。

软矿 的博主 MK 聊了一下,跟我推荐了几个 VPS,我看了半个下午的 VPS 套餐,确定下来之后发现人家卖完了,很无语。于是晚上将博客数据什么的搬回了之前的 JustHost 暂时用一下待日后再解决主机问题。虽然访问速度比较慢,但是至少不会出现那种打不开的抽风问题,使用 又拍云 进行静态文件加速,应该也不会慢到受不了。

WordPress 迁出 SAE 的步骤

这段虽然比较水,但是还是大体说一下,因为搬出来的时候遇到了一些小插曲,可供后来者参考使用。

WordPress 搬家步骤有很多,我个人比较喜欢的是:导出数据》》在目的主机安装 WordPress 》》导入数据。

这时候,强大的资源外链的作用体现出来了,因为图片等都用外链,所以根本不用管那些资源,直接把数据库内容转移即可。看起来步骤非常简单,但实际上从 SAE 迁移到 JustHost 的过程中遇到了很多问题,折腾了一个下午。

SAE 的数据导出问题

导出 WordPress 的数据有两种方式,第一种是在后台使用“工具”里面的“导出”,导出为 xml 文件,然后在新博客的后台直接导入即可。当然,这是一种不完全的导入方式,虽然说是博客全部的数据,但实际上只有文章、页面、简单的配置数据,一些博客名称什么的内容,还需要自己在新博客后台细微调整。

因为这种方式比较傻瓜,所以优先考虑。这时候出现问题了,SAE 上的 WordPress 无法导出所有的数据,只能导出 34kb 的 xml 数据文件。原因不详,看后台提示可能是因为 SAE 限制了数据查询次数还是其他乱七八糟的东西,反正导不出所有数据。不得已,我拿出前天导出的备份 xml 文件,大约 3M 左右大小。这时候要上传新博客的时候,发现服务商把 php 的上传限制在了 2M 大小。好吧,这种方法还得看你的主机参数配置,所以不是好办法。

SAE 上面也附带了 PHPMyAdmin 那就使用它直接把 MySQL 的数据库内容导出,然后在 JustHost 后台的 PHPMyAdmin 中导入好了。SAE 上的东西肯定都是阉割版的,不知道 PHPMyAdmin 是什么版本的,把数据库导出之后,在 JustHost 后台无法导入,因为某些语句出错。后来经过搜索,发现也有网友迁移的时候,遇到了这种问题。

SAE 还提供了一个他们自己开发的数据库管理服务 Deferred Jobs 可以用来导入导出 MySQL 数据库。因为使用这个服务需要排队等,不是立即生效的,所以官方推荐 4M 一下的数据库用 PHPMyAdmin 导入导出,4M 以上的使用这个服务。不管了,直接用了,其实没过多久就直接导出完毕。

下载下来 sql 文件有 3M 多,而使用 PHPMyAdmin 导出的才有 2M 多一点,我怀疑没有完全导出,难道又是被 SAE 阉割限制了?这次的 sql 文件非常正常,使用 JustHost 的后台 PHPMyAdmin 直接上传导入就可以了。

再全面的检查一下,增加一下固定链接伪静态,把主题文件、插件上传到新博客,这样搬家完成了,顺带升级成了最新版的 WordPress,SAE 上用的是 3.2.1 阉割版的 WordPress 大家都懂的。

感谢 SAE

我从2012年10月16号左右,把 WordPress 博客从 JustHost 迁移到了 SAE,后来总结写了《WordPress 迁移 SAE 完全操作攻略》 这篇文章,下面虽然有评论说看到很多人进去又出来了,但是我觉得我不会。因为我对 SAE 的服务挺有好感的,一直以为 新浪 是大公司,放在上面很安全,不会丢失数据也不会轻易被黑客攻击,可以安心写文章。以至于后面的这段时间,我连数据都没有备份过几次。

截止到今年3月份,博客在 SAE 上面已经5个多月了,这段时间内访问速度还是挺不错的,当然是相对于 JustHost 来说。对于小型的博客来说,花费非常少,我也做了很多优化,消耗资源很少,所以截止到现在的5个月的使用,算起来只花了2块钱的短信验证费,其他都是实名认证送的云豆。

同时通过 SAE,还学到了一些简单的 SVN 使用等。总之,虽然搬出了 SAE 还是要感谢它,日后一些小应用的开发什么的,说不定还会放在上面。感谢 SAE !

为什么不要用 SAE

在刚开始使用 SAE 的时候,对 SAE 充满了好感,曾经强烈推荐周围的朋友试用 SAE,也曾建议 多说 他们使用 SAE 或者 阿里云 主机,这样可以减少成本、人力消耗。因为他们的服务器都是自己购买,自己维护的,如果使用第三方稳定的服务,就可以仅仅专注于 多说 的开发了。但是他们拒绝了,我现在明白了。

东西只有掌握在自己手里,才是最安全的。SAE 或许比一些低端主机靠谱的多,但是为了开发或者资源限制,功能什么的阉割的太严重了。开发、修改等,都得按照他们的套路来,而放在自己的主机或者服务器上,想怎么处理就怎么处理(当然,你得有相关技术),无论是备份还是什么,都是很方便的。我想,多说团队之所以自己维护服务器,就是这个原因吧。

对我个人来说,可能也不会在 SAE 上寄放博客了,因为我本身要折腾 WordPress 所以在自己的主机上折腾比较方便,SAE 上的是早期阉割版本的 WordPress。

博客未来的发展

JustHost 虽然便宜,但是速度实在是比较慢,之前也是因为经常抽风宕机所以才想搬到 SAE 上面的。但是最近手头太紧,买好点的 VPS 又没有足够的资金,此外还有几个筹划中的网站项目等待上线。所以先暂时使用 JustHost,多写一些文章,等访问量大了,也有足够的资金,就会更换好点的主机,例如 linode 啥的。暂时先忍忍吧。

WordPress 子主题功能 + 为 WordPress 增加分类搜索功能并美化

近期关于 WordPress 方面主要写了两篇文章,分别是 使用 WordPress 的子主题(Child Themes)功能快速制作自己的主题为 WordPress 增加按分类搜索功能并自定义外观

之后,关于 WordPress 的文章,我直接首发在 我爱水煮鱼 上面,在 潜行者m 博客就不转发了,只对一些比较好点的文章做一个链接。欢迎大家关注 我爱水煮鱼,国内最专业的 WordPress 技术平台。

子主题功能

如果你想修改一个 WordPress 最好的方法并不是直接上去修改,而是通过 WordPress 的子主题功能进行修改。这样修改之后,不会影响到原来主题文件,原来主题升级覆盖之后,也不会影响你修改的内容。

结合着官方文档,并且动手实践了一下,写出了这篇文章:使用 WordPress 的子主题(Child Themes)功能快速制作自己的主题

增加分类搜索功能并定义外观

对于一个比较大型类门户的博客来说,按照分类搜索功能是必不可少的,这篇文章就介绍了如何增加这个功能。同时对输出的 select 分类选择下拉列表进行了美化。
这篇文章中,提供并用 jQuery 实现了模拟下拉列表的功能,想要围观请看这里:为 WordPress 增加按分类搜索功能并自定义外观

纯纯的超棒的写作工具:Writings.io

作为一个崇尚简约设计的博主,我对于写作环境的要求比较苛刻。先是用过 WordPress 的原生编辑器,然后觉得功能不够,使用增强版的编辑器插件,再到使用 Windows live write 这样的桌面写作软件,到现在的回归原始使用 WordPress 原生编辑器。这个过程中,我从要求功能的复杂转变到了简洁、简单。

但是 WordPress 原生编辑器仍然满足不了我追求简洁、愉快的写作体验,虽然它有全屏模式,但是切换神马的比较麻烦。自己如果修饰定义后台界面,工程又过于繁杂。偶然的机会,我发现了 Writings.io 这个工具。

可以这样说,如果 Writings.io 这个工具早点被开发出来,或许就不会有这个博客了,我会直接在那上面写作,用这个域名指向过去。相见恨晚。

Writings.io 简介

引用作者的话,就是说:

Writings.io 是一个提供在线文章写作、管理、发布的网站服务。整个网站采用清新简约的设计,学习 37signals 公司的理念,不求功能最多最全,但求简单够用。目前的 Writings.io 只有两个功能:文章管理和文章编辑。

其实作者也是简洁控,追求极致的写作乐趣,既然现有的已经无法满足,那么就自己动手开发个吧。看着这种介绍,我忍不住试了一下。

试用 Writings

先简单的注册一个账号,然后就进入了后台,及其简约的后台:

Writings 后台截图

然后很明显的新文章按钮,点击一下就进入了新写文章界面,超级简洁和必备的编辑功能:

Writings 文章编辑器截图

我把前段时间写的一篇文章复制上去测试一下,然后编辑器支持 HTML 代码,排版布局非常合理,写文章的普通基础功能都必备。点击一下发表之后就可以成功发布了,在此过程中实时的保存,妈妈再也不用担心我写的文章不见了。发布之后,就可以查看了。

Writings 文章发表之后截图

展示文章的样式也是非常简洁的,非常不错。后台其实有更强大的功能,比较亮的有这个:

Writings 后台亮点功能

支持绑定域名和 Disqus 账号,这样就可以自定义域名并且拥有评论功能了。绑定域名超级简单,直接 CNAME 到 writings.io 然后在后台设置一下,无需备案没有延迟,直接就可以使用了。

我做了一个小测试,绑定了一个域名然后发表了一片文章,大家可以点击看一下:http://test.qianxingzhem.com/

Writings 优势和未来发展

国内也有一些轻博客具有简约、专注于写作的特性,但是相比之下 Writings 做的更加极致,没有利益影响,没有框架和不必要的功能限制,单纯的享受写作的乐趣。

从前端技术的角度来看,整个网站前端做的非常好,采用了响应式的设计,同时 YSlow 性能测试得分 96 分。

目前还正在开发中,只由 Rei 一个人在开发,许多设想的功能还没有开发出来,例如:导出为 epub 格式、多人协作写作等等。欢迎大家亲自试用,然后提出相应的问题和需求。

为什么使用 class 属性来标注 HTML 元素而不是 id 属性

在网页中有很复杂的 HTML 结构,如果我们使用 CSS 来定义相关的样式,就需要为这些结构指定相应的标志,然后再编写相应的 CSS 选择器来获取他们赋予样式。最常用的两个标注属性就是 id 和 class 了,例如:

<div class=”header” id=”header” ></div>

现在还有更多的选择方法,例如:属性选择器等。但是并不推荐使用,使用属性选择器虽然可以省略掉 id 和 class,但是存在 后期维护起来不方便、早期浏览器兼容性不好、影响浏览器的渲染效率 等问题。所以,虽然有了更多的选择,我还是推荐使用 id 和 class 以及 元素名 来构造 CSS 选择器。

既然 id 和 class 都可以标注 HTML 结构,那么我应该优先选择使用什么?这就是本文即将讨论的。

id 和 class 的区别

有经验的朋友可以略过这一部分。

唯一性和重复可用性

id 在网页结构中只能是唯一的,如果你指定了一个元素的 id 为 aa,那么网页中就不能再出现一个 id 为 aa 的 HTML 元素。虽然强大的浏览器会支持多个重复 id 并赋予对应样式,但这是不标准不允许的。

而 class 相反,它可以在网页结构中重复使用,你指定了一个元素的 class 为 bb,同时可以指定下一个元素的 class 为 bb,这两个元素可以同时被应用 bb 的样式。此外,你还可以为一个元素制定多个 class 属性值,这样就会同时获得多个属性的样式。

CSS 中优先级不同

在 CSS 选择器中,对 id 和 class 的样式应用优先级不同。id 的样式优先级要高于 class 的样式优先级,如果我对一个 id 为 aa 、class 为 bb 的 div 指定了下面的样式:

#aa{background:red;}
.bb{background:blue;}

那么浏览器会显示成红色背景。

跳转功能

使用 id 属性可以增加锚标记跳转功能,如果在页面中我们对一个 div 指定 id 为 aa ,那么我们在当前的 URL 后面加上 #aa ,页面将会立刻跳转到 id 为 aa 的 div 所在的位置。例如:百度百科的章节跳转。而 class 没有这个功能。

http://baike.baidu.com/view/371.htm#8

为什么使用 class 而不是 id

使用 class 究竟有什么好处?

减少命名

为复杂的结构起名字真是一个麻烦的事情,如果我使用 id 来标注,那么我必须为每一个结构起一个名字。而在网页中,有很多结构的样式和效果都是一样的(例如:统一的按钮样式),那么我们仅仅编写一个通用的 class 样式,然后为所有的需要相同样式的结构赋值这个 class 即可。

高度重复使用

class 可以重复应用在其他结构中,并且可以对某个元素应用多个 class ,那么这样就可以高度重复使用某个 class 样式了。比较极端的实际应用就是原子类,例如:

.fl{float:left;display:inline;}
.fr{float:right;display:inline;}

尽可能小的简短的写出一些类,然后对于某个需要这个样式(例如:上面的浮动)的元素直接写上 class (例如:class=“fl”)。

一般的应用来说,对于某些需要相同样式的结构,只编写一个样式,然后对这些结构赋值相同的 class 即可,这样达到高度的样式代码重用,而且修改起来也比较方便。

优先级低

class 的优先级高于 元素名,低于 id ,利用优先级低的这个特性可以方便调试和样式覆盖。

如果我们之前对一个元素使用了 id 来标注,我们想修改这个元素的样式,只能去修改对应的 CSS 样式代码或者对某样式使用 !important 强调语法来覆盖原有样式。

如果元素使用了 class 来标注,那么我们直接为元素增加一个 id ,然后构造一个元素 id 的 CSS 选择器即可进行修改覆盖。

正是因为这些特性,所以要尽量使用 class 来标注元素,方便后期维护等。

id 也是必须有的

class 也不是万能的,有很多地方我们必须同时使用 id 来标注。

锚标记跳转

要想在页面中使用锚标记来跳转,那只能指定某个跳转目标的 id ,因为 class 可以被重复多次使用,所以不具备跳转的功能。

用在 input 中

使用 input 的时候,通常要使用 label 标签来描述这个 input 的功能。将 label 与 input 关联的方法有两种,一种是使用 label 的 for 属性,属性值就是 input 的 id 值,另一种就是将 label 把相应的 input 包裹起来。很显然第一种比较灵活比较好,但是你必须要对相应的 input 指定一个 id 属性。

此外,有些特殊的需求,也必须使用 id ,这里不再总结了。

最佳的使用组合

之前有很多批评 class 的言论,甚至有言论说 W3C 应该废除 class 标签,潜行者m 也曾经是 id 属性的狂热使用者,但是在实践过程中,越来越发现 class 的优点并改用 class。

比较好的使用组合就是对于绝大多数的元素和结构等使用 class 来指定,对于极个别需求特定功能的元素使用 id 标注。

欢迎讨论交流。