浅谈Web缓存

来自:腾讯AlloyTeam Blog

by TAT.yana

链接:http://www.alloyteam.com/2016/03/discussion-on-web-caching/(点击尾部阅读原文前往)

在前端开发中,性能一直都是被大家所重视的一点,然而判断一个网站的性能最直观的就是看网页打开的速度。其中提高网页反应速度的一个方式就是使用缓存。一个优秀的缓存策略可以缩短网页请求资源的距离,减少延迟,并且由于缓存文件可以重复利用,还可以减少带宽,降低网络负荷。那么下面我们就来看看服务器端缓存的原理。

缓存分类

web缓存分为很多种,比如数据库缓存、代理服务器缓存、还有我们熟悉的CDN缓存,以及浏览器缓存。对于太多文字的阅读其实我是拒绝的,于是就画了个图来解释下。

浏览器通过代理服务器向源服务器发起请求的原理如下图,

浏览器先向代理服务器发起Web请求,再将请求转发到源服务器。它属于共享缓存,所以很多地方都可以使用其缓存资源,因此对于节省流量有很大作用。

浏览器缓存是将文件保存在客户端,在同一个会话过程中会检查缓存的副本是否足够新,在后退网页时,访问过的资源可以从浏览器缓存中拿出使用。通过减少服务器处理请求的数量,用户将获得更快的体验

下面我就来着重讲下传说中的浏览器缓存。

浏览器缓存

页面的缓存状态是由header决定的,header的参数有四种:

一、Cache-Control:

1、max-age(单位为s)指定设置缓存最大的有效时间,定义的是时间长短。当浏览器向服务器发送请求后,在max-age这段时间里浏览器就不会再向服务器发送请求了。

我们来找个资源看下。比如shang.qq.com上的css资源,max-age=2592000,也就是说缓存有效期为2592000秒(也就是30天)。于是在30天内都会使用这个版本的资源,即使服务器上的资源发生了变化,浏览器也不会得到通知。max-age会覆盖掉Expires,后面会有讨论。

2、s-maxage(单位为s)同max-age,只用于共享缓存(比如CDN缓存)。

比如,当s-maxage=60时,在这60秒中,即使更新了CDN的内容,浏览器也不会进行请求。也就是说max-age用于普通缓存,而s-maxage用于代理缓存。如果存在s-maxage,则会覆盖掉max-age和Expires header。

3、public 指定响应会被缓存,并且在多用户间共享。也就是下图的意思。如果没有指定public还是private,则默认为public。

4、private 响应只作为私有的缓存(见下图),不能在用户间共享。如果要求HTTP认证,响应会自动设置为private。

5、no-cache 指定不缓存响应,表明资源不进行缓存,比如,

但是设置了no-cache之后并不代表浏览器不缓存,而是在缓存前要向服务器确认资源是否被更改。因此有的时候只设置no-cache防止缓存还是不够保险,还可以加上private指令,将过期时间设为过去的时间。

6、no-store 绝对禁止缓存,一看就知道如果用了这个命令当然就是不会进行缓存啦~每次请求资源都要从服务器重新获取。

7、must-revalidate指定如果页面是过期的,则去服务器进行获取。这个指令并不常用,就不做过多的讨论了。

二、Expires

缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点。也就是说,Expires=max-age + 请求时间,需要和Last-modified结合使用。但在上面我们提到过,cache-control的优先级更高。 Expires是Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。

三、Last-modified 

服务器端文件的最后修改时间,需要和cache-control共同使用,是检查服务器端资源是否更新的一种方式。当浏览器再次进行请求时,会向服务器传送If-Modified-Since报头,询问Last-Modified时间点之后资源是否被修改过。如果没有修改,则返回码为304,使用缓存;如果修改过,则再次去服务器请求资源,返回码和首次请求相同为200,资源为服务器最新资源。

如下图,最后修改时间为2014年12月19日星期五2点50分47秒

四、ETag

 

根据实体内容生成一段hash字符串,标识资源的状态,由服务端产生。浏览器会将这串字符串传回服务器,验证资源是否已经修改,如果没有修改,过程如下:

使用ETag可以解决Last-modified存在的一些问题:

a、某些服务器不能精确得到资源的最后修改时间,这样就无法通过最后修改时间判断资源是否更新

b、如果资源修改非常频繁,在秒以下的时间内进行修改,而Last-modified只能精确到秒

c、一些资源的最后修改时间改变了,但是内容没改变,使用ETag就认为资源还是没有修改的。

使用缓存流程

还是用图说话,下面是我所总结的从浏览器请求到展示资源的过程:

cache-control指令使用

说了那么多cache-control的指令,那么如何选择使用哪些指令呢?我还是不说话==

额外的

除了开头提到的那么多缓存方式以外,还有一种我们都熟悉的缓存方式,LocalStorage和sessionStorage(好像是两种23333)。

LocalStorage是一种本地存储的公共资源,域名下很多应用共享这份资源会有风险;LocalStorage是以页面域名划分的,如果有多个等价域名之间的LocalStorage不互通,则会造成缓存多份浪费。

LocalStorage在PC上的兼容性不太好,而且当网络速度快、协商缓存响应快时使用localStorage的速度比不上304。并且不能缓存css文件。而移动端由于网速慢,使用localStorage要快于304。

在html中加载一个png图,首次加载的时候时间如下图,

然而将图片使用了LocalStorage存储后,再次刷新后加载时间为0。

而相对LocalStorage来说,SessionStorage的数据只存储到特定的会话中,不属于持久化的存储,所以关闭浏览器会清除数据。和localstorage具有相同的方法。

在前端开发中缓存是必不可少的,那么使用怎样的缓存方式更高效、让我们项目的性能更优,还是需要我们仔细斟酌。

如何正确学习JavaScript(写给非JavaScript程序员和编程新手)

来自:crimx.com

链接: http://www.crimx.com/2014/05/15/how-to-learn-javascript-properly

原文:http://javascriptissexy.com/how-to-learn-JavaScript-properly/

翻译:Jaward华仔

目录

  • 不要这样学习JavaScript
  • 本课程资源
  • 1~2周(简介,数据类型,表达式和操作符)
  • 3~4周(对象,数组,函数,DOM,jQuery)
  • JavaScript终极编辑器:WebStorm
  • 第一个项目-动态问答应用
  • 5~6周(正则表达式,Window对象,事件,jQuery)
  • 7周,可延长到8周(类,继承,HTML5)
  • 继续提升
  • 一些鼓励的话

既然你找到这篇文章来,说明你是真心想学好JavaScript的。你没有想错,当今如果要开发现代网站或web应用(包括互联网创业),都要学会JavaScript。而面对泛滥的JavaScript在线学习资源,却是很难找到一份高效而实用的方法去学习这个“web时代的语言”。

有一点需要注意,几年前我们需要知道一个真正的服务器端语言(比如PHP,Rails,Java,Python 或者 Perl)去开发可扩展,动态的,数据库驱动的web应用,而现在只用JavaScript就可以实现了。

学习时长:6~8周

学习前提:中学水平,无需编程经验

在Reddit上创建了一个学习小组

January 2014, “Learn JavaScript” Study Group on Reddit

上面的课程大纲提供了一个结构化和富有启发性的学习线路,从初学者到有所建树,把JavaScript学对学透。

不要这样学习JavaScript

不要一开始就埋头在成堆的JavaScript在线教程里 ,这是最糟糕的学习方法。或许在看过无数个教程后会有点成效,但这样不分层次结构地学习一个东西实在是十分低效,在实际用JavaScript建立网站或web应用时你还是会频繁的卡住。总的来说,这种学习方法会让人不知道如何将语言当做工具来使用——当做个人工具来用。

另外,也许有人会建议从尊敬的JavaScript教父Douglas Crockford写的《JavaScript语言精粹》开始学习JavaScript。然而,虽然Crockford先生对JavaScript无所不知,被誉为JavaScript世界的爱因斯坦,但他的《JavaScript语言精粹》并不适合初学者学习。这本书没有通透、清晰、明了的阐述JavaScript的核心概念。但对于更高级的学习路线,我倒会建议你看看Crockford先生的视频。

还有,不要只从Codecademy等网站学习JavaScript,因为即使知道怎么编写一大堆JavaScript代码小片段,还是不能学会怎么建立一个web应用程序。即便如此,在后面我还是会建议把Codecademy当做补充的学习资源。

本课程资源

更新:Reddit用户d0gsbody4月8号在Reddit上建立了一个学习小组。他和其他组员都非常积极和乐于助人。我建议你加入这个小组,他们会让你保持积极性且帮助你更好的学习JavaScript。毕竟独自折腾JavaScript还是有点难度的。链接:Learning JS Properly – Study Group on Reddit

  • 请在以下两本书中选一本,第一本比较适合有编程经验的人,而另一本则适合完全没有编程经验的初学者。我个人推荐第一本书,因为作者对各个知识点都阐述得非常好且涵盖了一些高级JavaScript知识点。但是,要看懂这本书你至少要对web开发有一定的基本了解。所以,如果你有一点点编程经验或者web开发经验(不一定是JavaScript),那就买这本书吧。
      • 纸质版(英文) :Professional JavaScript for Web Developers
      • 纸质版(中文) :JavaScript高级程序设计(第3版)
      • Kindle版(英文):Professional JavaScript for Web Developers
      • Kindle版(中文):JavaScript高级程序设计(第3版)

如果你没有编程经验,可以买这本:

    • 纸质版(英文) :JavaScript: The Definitive Guide
    • 纸质版(中文) :JavaScript权威指南(第6版)
    • Kindle版(英文):JavaScript: The Definitive Guide
    • Kindle版(中文):JavaScript权威指南(原书第6版)
  • 免费注册Stack Overflow,这是一个编程领域的问答论坛。在这里提问题得到的回答比Codecademy要好,哪怕你的问题非常基础,看起来很傻(记住,从来没有愚蠢的问题)。
  • 免费注册Codecademy,这是一个在线学习平台,你可以直接在浏览器里面写代码。
  • JavaScriptIsSexy上的一些博文,包括对象,闭包,变量的作用域和提升,函数等等。

JavaSctipt学习路线

完成整个课程大纲需要花上6~8周的时间,将学会完整的JavaScript语言(包括jQuery和一些HTML5)。如果你没有时间在6个星期里完成所有的课程(确实比较有挑战性),尽量不要超过8个星期。花的时间越长,掌握和记忆各种知识点的难度就越大。

1~2周(简介,数据类型,表达式和操作符)

如果你还不是很了解HTML和CSS,完成Codecademy上的web基础任务。

阅读《JavaScript权威指南》或者《JavaScript高级程序设计》的前言和第1~2章。

十分重要:在书中遇到的每个样例代码都要动手敲出来并且在火狐或Chrome浏览器控制台中跑起来、尽量蹂躏它(做各种试验)。也可以用jsfiddle,但不要用Safari浏览器。我建议用火狐搭配Firebug插件去测试和调试代码。浏览器控制台就是可以让你编写和运行JavaScript代码的地方。

完成Codecademy?JavaScript Track上的Introduction to JavaScript部分。

阅读《JavaScript权威指南》第3~4章。或者阅读《JavaScript高级程序设计》第3~4章。你可以跳过位操作部分,在你的JavaScript生涯中一般不会用上这个。

再次说明,记得要不时停下来把书本的代码敲到浏览器控制台里(或者JSFiddle)做各种测试,可以改变几个变量或者把代码结构修改一番。

阅读《JavaScript权威指南》第5章。至于《JavaScript高级程序设计》则暂时没有阅读任务,因为前面已经把相关知识覆盖了。

完成Codecademy?JavaScript Track上的2~5部分。

3~4周(对象,数组,函数,DOM,jQuery)

以下三选一:

  • 阅读我的博文JavaScript 对象详解.
  • 阅读《JavaScript权威指南》第6章。
  • 阅读《JavaScript高级程序设计》第6章。注意:只需要看“理解对象”(Understanding Objects)部分。

两本书会涉及更多的一些细节,但只要看完我的博文,你可以完全放心地跳过这些细节。

1、阅读《JavaScript权威指南》第7~8章或者《JavaScript高级程序设计》第5和7章。

2、此时,你应该花大量时间在浏览器控制台上写代码,测试if-else语句,for循环,数组,函数,对象等等。更重要的是,你要锻炼和掌握独立写代码,不用借助Codecademy。在Codecademy上做题时,每个任务对你来说应该都很简单,不需要点帮助和提示。如果你还卡在Codecademy上,继续回到浏览器上练习,这是最好的学习方法。就像詹姆斯年轻时在邻居的篮球场上练球,比尔盖茨在地下室里学习编程。

持续地练习,这一点点的进步积累起来效果会非常惊人。你要看到这个策略的价值,相信它是可行的,全心投入进去。

**Codecademy会造成已掌握的错觉。**

使用Codecademy最大的问题是,它的提示和代码小片段会让人很容易就把答案做出来,造成一种已经掌握这个知识点的错觉。你可能一时看不出来,但这样做你的代码就不是独立完成的了。

但目前为止,Codecademy依然是学习编程的好帮手。特别是从一些基本的代码结构如if语句,for循环,函数和变量去指导你了解小项目和小应用的开发过程。

1、回到Codecademy完成JavaScript路线。做完6~8部分(数据结构做到Object 2)。

2、实现Codecademy上Projects路线的5个基础小项目(Basic Projects)。做完之后,你已不再需要Codecademy了。这是一件好事,因为自己做的越多,学得就越快,就能更好准备开始独立编程。

3、阅读《JavaScript权威指南》第13,15,16和19章。或者阅读《JavaScript高级程序设计》第8,9,10,11,13和14章。这本书没有涉及到jQuery,而Codecademy上的jQuery知识也覆盖得不够。可以看看jQuery的官方教程,免费的:http://try.jquery.com/

你也可以在《JavaScript权威指南》第19章了解更多的jQuery知识。

完成全部的jQuery教程http://try.jquery.com/

JavaScript终极编辑器:WebStorm

在你实现第一个项目之前,如果打算以后做JavaScript开发者或者经常用到JavaScript,最好现在就去下载WebStorm的试用版。这里可以学习怎么使用WebStorm(专门为这个课程写的)。毋庸置疑,WebStorm是JavaScript编程最好的编辑器(或IDE)。30天试用后要付$49.00,但作为JavaScript开发者,这应该是除了买书以外最明智的投资了。

确保在WebStorm中启用JSHint。JSHint是一个检查JavaScript代码错误和潜在问题的工具,强制你的团队按照规范写代码。用WebStorm最爽的地方是JSHint会自动在错误的代码下显示红线,就像文字处理程序中的拼写检查。JSHint会显示一切的代码错误(包括HTML),促使你养成良好的习惯,成为更好的JavaScript程序员。这很重要,当你真正意识到WebStrom和JSHint对你的巨大帮助时,你会回来感谢我的。

此外,WebStorm是一个世界级,专业人员使用的IDE,用来编写专业的JavaScript web应用,所以你以后会经常用到它。它还结合了Node.js,Git和其它JavaScript框架,所以即使你成为了明星级的JavaScript开发者,你还是会用到它的。除非以后出现了更多的JavaScript IDE。

公平起见,我在这里提一下Sublime Text 2,这是仅次于WebStorm的JavaScript编辑器。它的功能不及WebStorm丰富和完整(即使添加了一堆插件)。做小修改的时候我会用到Sublime Text 2,它支持很多语言,包括JavaScript,但我不会用它来构建完整的JavaScript Web应用。

第一个项目-动态问答应用

此时,你已经掌握了足够的知识去建立一个稳固的,可维护的web应用。在做完我为你设计的这个应用之前不要看后面的章节。如果你卡住了,去Stack Overflow提问并且把书上相关的内容重新看一遍直到完全理解这些概念。

接下来开始建立一个JavaScript问答应用(还会用到HTML和CSS),功能如下:

// 这里只演示一个问题,你要把所有问题都添加进去

var allQuestions = [

{

question: “Who is Prime Minister of the United Kingdom?”,

choices: [

“David Cameron”,

“Gordon Brown”,

“Winston Churchill”,

“Tony Blair”],

correctAnswer: 0

}

];

  • 当用户点击“Next”时,使用document.getElementById或jQuery动态的添加下一个问题,并且移去当前问题。在这个版本里“Next”是唯一的导航按钮。
  • 你可以在本文下方评论求助,最好是去Stack Overflow提问,在那里会有及时而准确的回答。

5~6周(正则表达式,Window对象,事件,jQuery)

阅读《JavaScript权威指南》第10,14,17,20章。

或者阅读《JavaScript高级程序设计》第20,23章。

1、记得要把样例代码敲到浏览器控制台上,尽可能蹂躏它,做各种测试,直到完全理解它是怎么工作,它能干些什么。

2、此时,你用起JavaScript来应该很顺手,有点像武林高手要出山了。但你还不能成为高手,你要把新学到的知识反复使用,不停的学习和提升。

3、升级之前做的问答应用

  • 添加客户端数据验证:保证用户回答了当前问题才能进入下个问题。
  • 添加“Back”按钮,允许用户返回修改答案。最多可以返回到第一个问题。注意对于用户回答过的问题,选择按钮要显示被选中。这样用户就无需重新回答已经答过的问题。
  • 用jQuery添加动画(淡出当前问题,淡入下个问题)
  • 在IE8和IE9下测试,修改bug,这里应该会有得你忙了。 ;D
  • 把问题导出JSON文件
  • 添加用户认证,允许用户登陆,把用户认证信息保存在本地存储(local storage,HTML5浏览器存储)。
  • 使用cookies记住用户,当用户再次登陆时显示“欢迎用户名回来”。

7周,可延长到8周(类,继承,HTML5)

阅读《JavaScript权威指南》第9,18,21,22章。

或者阅读我的博文JavaScript面向对象必知必会

或者阅读《JavaScript高级程序设计》第6,16,22,24章,第6章只读“创建对象”(Object Creation)和“继承”(Inheritance)部分。注意:这部分是本课程中技术性强度最大的阅读,要根据自身的状况考虑要不要全部读完。你至少要知道原型模式(Prototype Pattern),工厂模式(Factory Pattern)和原型继承(Prototypal Inheritance),其它的不作要求。

1、继续升级你的问答应用:

  • 页面布局使用Twitter Bootstrap,把问答的元素弄得看起来专业一些。而作为额外奖励,用Twitter Bootstrap的标签控件(译者注:原文地址失效,已改)显示问题,每个标签显示一个问题。
  • 学习Handlebars.js,将Handlebars.js模板用在问答应用上。你的JavaScript代码中不应该再出现HTML代码了。我们的问答应用现在越来越高级啦。
  • 记录参加问答的用户成绩,展示用户在问答应用中与其他用户的排名比较。

2、在学完Backbone.js和Node.js后,你会用这两种最新的JavaScript     框架重构问答应用的代码,使之变成复杂的单页面现代web应用。你     还要把用户的认证信息和成绩保存在MongoDB数据库上。

3、接下来:构思一个项目,趁热打铁迅速的去开发。卡住的时候参考     《JavaScript权威指南》或者《JavaScript高级程序设计》。当然     ,还要成为Stack Overflow的活跃用户,多问问题,也要尽量回答     其它人的提问。

继续提升

1、精通backbone.js

2、中高级JavaScript进阶

3、不侧漏精通Node.js

一些鼓励的话

祝你学习顺利,永不放弃!当你做不下去觉得自己很蠢的时候(你会时不时这么想的),请记住,世界各地的其他初学者,甚至是有经验的程序员,也会不时产生这种想法的。

如果你是完全的初学者,特别是过了青少年时期的人,开始写代码的时候也许很困难。年轻人无所畏惧,也没有什么负担,他们可以花大量的时间在喜欢的东西上。所以各种挑战对他们来说也不过是短暂的障碍罢了。

但过了青少年期后你会希望快速的见到成效。因为你没有这么多的时间去花上几个小时就为了搞清楚一些细节的东西。但这些东西你必须深入去理解它,不要因此沮丧,坚持完成课程的任务,把bug都找出来,直到你完全理解。当你到达胜利的彼岸时,你会知道这一切都是值得的,你会发现编程非常有趣而且在上面花的时间都会得到可观的回报。

一个人必须去感受和领悟构建程序带来的强烈快感。当你一步步的掌握知识点,一点点的将程序搭建起来时,就会对自己产生激励与肯定,带来十分美妙的满足感。

总有一天你会意识到之前忍受的所有困难都是值得的。因为你将要成为一名光荣的程序员,你也清楚作为JavaScript开发者,你的前途一片光明。就像在你之前成千上万的程序员一样,你打败了最难的bug,你没有退步,你没有放手,你没有找任何借口让自己放弃。

当你学有所成的时候,放心的将你的成果分享给我们吧,哪怕是个微不足道的,小到显微镜都看不到的小项目。

有图有案例!125个提升网页可用性的优化小技巧(三)

英文:nickkolenda

译者:企业官网设计精选

链接:http://www.uisdc.com/125-website-usability-optimize-3#

编者按:这个系列的教程有125个实用的网页优化技巧,每一个技巧都有案例阐述,保证简单易懂。今天企业官网设计精选 翻译了第三部分 —— 在网页设计中如何少让用户费脑筋,保持操作流畅。一起来收!

往期回顾:

  1. 《有图有案例!125个提升网页可用性的优化小技巧(一)》
  2. 《有图有对比!125个提升网页可用性的优化小技巧(二)》

除了引导用户,还要减少他们的认知流程,以保持流畅状态。

尽可能少让用户做计算

千万别把计算这种事情丢给用户,让计算机来处理。

△ 显示剩余数量

在界面内体现用户当前所处位置

界面就像机场,如果没有“你在这里”的标记,用户会迷路,因此记得提供标记。

△ 在导航菜单上突出当前所选

△ 在复杂的界面中提供面包屑导航或步骤图示

△ 在页面标题前面部分放置描述性或有用的信息

 

简化选择类任务

做选择需要费脑筋,简化这类任务让用户少费神

△ 指明多数用户选择的选项

△ 提供常见搜索关键词列表

△ 下拉分类菜单置于相应导航菜单内

 

使用常规的网页设计界面

创新很好,但不要跟常规的设计方式偏离太远。用户习惯于某些布局、结构。常规设计之所以流行,是因为他们确实可行。

△ 使用常规的导航菜单

△ 把实用功能放在右上角

 

每次交互动作后提供反馈

用户跟界面进行互动后,需获得实时反馈。操作成功还是失败了?发生了什么变化?

△ 重要的交互动作后反馈提示成功消息

△ 显示当前鼠标停留在哪个项目上

 

最小化等待的负面效果

消灭所有不必要的等待。如果确实要用户等,则最小化该负面效果。

△ 加载动画效果使用冷色调减少对用户刺激

蓝色减少刺激(提高放松程度),蓝色加载元素可让用户觉得加载更快(Gorn et al., 2004)。

△ 长时间等待时保持用户活跃度(别人他们干等)

△ 防止用户上传不支持的文件

△ 实时统计显示任务进展

 

尽可能减少用户对记忆的依赖

别让用户去记住任何东西,将相关信息显示出来

△ 让表单标签保持一直可见

△ 避免用户点击后就消失的行内标签

△ 占位文本放到表单元素的外边

△ 为可移动输入添加复制按钮△ (△ Add Copy Buttons to Movable Input△ )

 

尽量少用锯齿状视图模式

减少用户眼睛来回移动的次数,让各项补充数据保持接近。

△ 合并相同的数据字段帮助用户进行对比

△ 让表单标签紧贴相应元素并对齐

 

反馈显示哪些项目是可点击或交互的

用户需要识别哪些元素是可交互的(并且知道如何交互)。

△ 使用3D特性设计按钮

△ 为可拖拽元素添加点状纹理

△ 使用图标和符号传达一个交互动作的意图

你可以通过PowerPoint 或 Keynote的各种形状制作大部分图标

 

用常见的文字和符合来沟通

大多数情况下,清晰明确胜过创意和术语

△ 讲用户懂的语言,不讲程序语言

△ 出现外语时,提供翻译按钮

△ 颜色的选择要与语义保持一致

当颜色跟语义不一致时,会增加用户处理信息的困扰。如meetup.com上使用红色确认出席,准确应该是用绿色。

 

尽可能提高界面的可浏览性

多数用户采用浏览扫读的方式处理内容,我们需要接受这种行为。

设计界面时尽量适应这种泛读浏览方式。

△ 保持段落简短,高亮关键词组

△ 把重要信息放在列表的开头

△ 给表格添加交替的行条纹背景

△ 编写独立副标题(不要一篇文章就一个大标题)

△ 用视觉变化拆分文本

 

尽可能提高文本的可读性

很明显,文本需要让人易懂,有些技巧能让文本更具可读性。

△ 让文本和背景具有鲜明对比

背景上显示文本需要注意,可能需要做一些叠加或模糊处理。(以作者照片为例…)

△ 正文的主要部分采用左对齐

 

界面设计风格保持一致

风格不统一的话用户需要花更多时间学习界面。保持统一的布局和外观可以简化学习过程。

△ 制定一份前端风格指引

制定一份稳定,总结界面各元素的设计规格说明

其他元素包括:

  • 颜色
  • 网格和布局
  • 位置和定位
  • 大小和形状
  • 标签和语言
  • 导航
  • 表格
  • 列表
  • 链接
  • 声音和腔调

需要灵感参考?看看Mailchimp的风格指引(http://ux.mailchimp.com/patterns)

△ 导航菜单保持在相同位置

 

通过视觉平衡实现设计美感

美观的设计更加好用 – 即美即好用效应原则(Kurosu & Kashimura, 1995)。

△ 使用数学原理构造设计

△ 使用对比性字体

挑选搭配字体时,有人喜欢使用相似的字体,但这种方式是错的,很多时候相似的看上去并不对。

相反,应该精心挑选对比鲜明的字体,新手设计师可以选择serif vs sans-serif(英文字体),如上图

未完待续…

有图有对比!125个提升网页可用性的优化小技巧(二)

英文:nickkolenda

译者:企业官网设计精选

链接:http://www.uisdc.com/125-website-usability-optimize-2

这个系列的教程有125个实用的网页优化技巧,每一个技巧都有案例对比,保证简单易懂。今天翻译了第二部分 —— 在网页设计中帮助用户实现目标,一起来涨姿势!

第一期回顾:《有图有案例!125个提升网页可用性的优化小技巧(一)

让常用功能和重要数据信息更接近用户

预测用户的意图,让他们尽可能接近目标。

△ 筛选出或跳至用户正在搜索的条目

△ 将用户常选项目列为默认选项

△ 产品列表页上把重要数据信息展示出来

很多时候用户需要像踩弹簧高跷杖一样,点击一个产品,查看信息,返回上一页,再反复操作以查看其他产品。这种设计的可用性差。应把重要信息直接放在主要页面,减少用户反复操作的次数。

如果你怕这样页面会杂乱,也可以设计成鼠标悬停时显示(如下面这样)

△ 鼠标悬停时显示有用信息

△ 常用功能直接展示出来

△ 用仪表面板方式展现主要数据和状态

△ 把常见答案放在下拉列表的头部

交互状态的及时反馈呈现

通过传达所有相关信息减少不确定性。

△ 在机器驱动的任务中显示当前进度和剩余时间

如上传文件是系统在处理,用户不知道内部运作情况,通过显示进度条可以让用户知道进展。

△ 复杂或冗长的交互状态要及时反馈呈现

△ 按次序显示操作步骤总数

△ 显示类目下的条目数

同一任务,可为客户提供多种完成方式

用户喜欢的操作方式不一样。为同一目标提供不同路径,让用户选择最符合他们自己的方式。

△ 用户可通过用户名或电子邮件登录系统

△ 为重复操作类功能提供键盘快捷键

△ 让用户可以拖拽元素

△ 让用户直接编辑数据信息

反馈呈现交互动作的限制条件或参数要求

为每一个交互动作做好准备。用户需要什么?他们如何继续?

△ 描述清楚你需要用户输入什么

△ 实时显示密码要求并反馈输入状态

△ 为表单元素预填通用参数

△ 显示表单的必填和选填信息

反馈显示交互动作的预期结果

在用户进行交互操作之前,他们应该了解预期结果是什么

△ 使用描述性按钮标签

△ 根据当前的输入,显示结果预览

△ 按次序显示或预览下一个项目

△ 使用智能菜单项明确操作内容

当用户取得进展时,给予奖励或肯定

用户取得进展了吗?他们的交互成功了吗?让用户知道,同时引导他们继续。

△ 保证链接与目标页面的一致性

△ 为新加入用户提供速效指引环节(如迅速建立人脉)

△ 进度条从大于0%的地方开始

解决用户的核心需求

很多时候,我们只解决了用户的表层需求。深入下去,探究为何用户需要某些功能或信息,然后解决他们的底层需求

△ 显示当前时间办公室处于开放还是关闭状态

△ 显示事件的新近状态

如最近发表的评论,显示为几天之前而不是具体日期,用户可明确感知是新评论。

未完待续…

有图有案例!125个提升网页可用性的优化小技巧(一)

英文:nickkolenda

译者:企业官网设计精选

链接:http://www.uisdc.com/125-website-usability-optimize-1#

编者按:这个系列的教程到目前为止有5个章节,共125个实用技巧,每一个技巧都有案例对比,保证简单易懂。今天翻译了第一部分 —— 在网页设计中如何引导用户的注意力。学会一个就能受用无穷,更别说这一章整整有17个具体的方法了。

在界面中突出强调一个聚焦点

每个界面都应该有一个清晰的起点。用户应该从哪里看起?要设计清楚。

△ UX策略1 – 在页面标题部分添加视觉对比

通过视觉的层次引导用户

通过界面引导控制用户体验。他们应该从哪里先看起,第二和第三步又看哪里?设计要建立层次结构。

△ UX策略2 – 避免在构图中补漏留白

△ UX策略3 – 使用单列布局

△ UX策略4 – 重叠设计元素,强调连续性

使用格式塔原则进行布局设计

根据格式塔心理学,人会通过简化感知克服混乱。所以我们将事物分组,将元素分类,我们看“整体”。

这些原则包括:相似,接近,闭合,连接,连续和图形/背景。

△ UX策略5 – 按照接近性将相似功能或菜单项分组显示

△ UX策略6 – 标题位置与对应章节内容更靠近

△ UX策略7 – 限制标题与章节内容在同一界限内

在不干扰用户的前提下呈现界面变化

有一些界面变化会发生在用户使用期间,这些变化要做到明显但不干扰用户。

△ UX策略8 – 用明显的动画呈现界面变化

△ UX策略9 – 将出错的元素区分显示出来,错误提醒信息放置在表单顶部

删除或弱化不必要的信息

人的注意力是有限的。不必要的元素会消耗这些注意力。因此,保持用户专注在重要信息和功能上。

△ UX策略10 – 弹出或模态窗口背景模糊处理

△ UX策略11 – 在所有图像中最大限度地提高数据墨水比率(让数据更凸显)

△ UX策略12 – 去掉不必要的边框

△ UX策略13 – 删除冗余或不言自明的说明

△ UX策略14 – 隐藏不常用但必要的设置、功能和信息

提示首屏以下是否还有内容

现在大多数浏览器在页面处于非活动状态时隐藏滚动条,你需要“滚动提示”告知用户首屏以下是否还有内容

△ UX策略15 – 通过首屏延伸页面下方信息元素

△ UX策略16 – 添加阴影以指示深度

△ UX策略17 – 用文字或图形表示有更多内容

响应式网页设计排版需要注意什么?

出处:前端资源网

链接:http://www.58img.com/design/2495

斯坦佛大学的一份研究报告证实,75%的用户承认自己会通过一个公司的网站来评价该公司的声誉。由此可见,优秀的网页排版对于公司的形象和转换率有重要作用。毫无疑问,网页必须以有吸引力的,高效的方式方式呈现信息。问题是,目前有很多不同类型的移动设备,而网页排版必须符合所有这些平台的规范。

那么,我们究竟该如何实现最佳的网页排版效果呢?

1. 精心挑选字体将为你赢得灵活而高效的排版

自从客户端字体(Font Face)被引入网页设计中之后,网页设计师们便拥有了将不同字体用于自己设计中的自由。此前,他们只能使用特定的,与网页安全兼容的字体。

但面对这些可以自由使用的字体,设计师们还需要知道如何正确地使用它们。响应式网页设计已经成为多数网站的标准设计模式,不过由于要顾及不同尺寸的设备屏幕,它对网页排版也提出了一些限制。所以网页设计师在一个响应式网页系统中使用多种字体时,必须十分审慎。在同一个网站中不要使用太多种字体,最好不要超过三种。同时也不要使用极为流行的字体,这并不能让你的网页看起来比别的网页更有优势。

案例分析

这个站点使用了两种无衬线字体。所有的标题使用的都是Balto 字体,正文采用的是Alright Sans 字体。介于这两者之间的是Harriet 字体。整个页面外观显得十分简洁优雅。

http://www.vox.com/

与之形成对比的是angelfire 网站,这个站点使用了多种不同的字体,看起来混乱,不专业。

2. 突出显示标题

网页排版的一个特点就是标题在版式中占据突出位置。别致的标题能吸引用户在你的网站停留更久。为了实现这一点,你可以利用字形(glyphs)和连字(ligatures)技巧创造外观更独特的标题。

连字指的是看起来似乎是连接在一起的字母。例如,单词“fish”中的f和i在某种字体里可能联成一体(fi)。通过浏览器的字体设置功能或借助“文本渲染——优化清晰度”(Text Rendering- OptimiseLegibility)特性, 你可以轻松地实现连字效果。火狐浏览器已经设置了默认的连字符。在某些字体中使用特定的连字组合效果能为你的网页版式增加美感和风格。在网页排版软件的Text, Type 或Open Type目录中,一般都可以开启或关闭连字效果。当合适的字母相邻出现时,这些软件会自动为它们设置连字效果。

案例分析

请注意这个网站中优雅的连字。这些优美的字体如果用于网页标题中的话,无疑会为访客带来更为卓越的用户体验。

http://iloveligatures.tumblr.com/

3. 合理搭配不同大小和颜色的字体

正如上面的图片所传递的信息一样,我们在网页设计中必须选择能在桌面端和移动设备屏幕上都清晰显示的字体。一款字体在印刷品中与在数码设备中显示的效果是不同的。因此我们必须理解font family属性,风格和效果。根据W3C对于CSS字体的规定,Serif, Sans-Serif, Monospace, Fantasy 和Cursive等字体都具有font family属性。

第二,应根据网站的主题或分类来选择字体。这样才能确保你的网页能引起目标受众的共鸣,达到想要的效果。衬线字体同样能用于提升文本的阅读效果,强化要传达的信息。这里的问题是,衬线字体的特性决定了它只能在高解析度的屏幕上正常显示,在低解析度的屏幕上可能会导致糟糕的结果。因此建议你在短标题中使用艺术字体,在正文中采用更简洁的字体。

4. 在响应式排版中,调节行宽十分重要

必须对网页中的行宽(line length )进行调节,因为字体的行宽与排版的响应程度息息相关。响应式设计也包括在不同尺寸的屏幕上字体所发生的自适应式改变。所以调整字体的行宽是必须的。

理想的行宽为每行文本中字符数量在45-47之间,包含空格和标点。最长的限度我45-85个字符。这是对人们的阅读习惯和眼动规律做出研究后得出的结论。根据这一结论,有专家建议网页内容采用左对齐的排版方式,因为人的视线在阅读时一般会按照从左至右的方式在水平方向上运动。

案例分析

网站suite 将没行文本的字符数限定为75个。正如你能看到的,页面中的文本看起来十分优美,能让用户怀着兴趣一直读下去。

https://suite.io/

5.当用户与屏幕的距离不同时,使用不同大小的字体能改善可读性。在响应式排版设计中,必须考虑这一点。

字体的大小要能保证字体在设备上可见,可读。而要做到这一点,可能会与前面所说的保持“理想行宽”发生冲突。因为“理想行宽”意味着要调小或调大字体尺寸,而这两者都可能导致文本不可读。这里的底线是要保证浏览者能舒服地阅读网页内容。响应式设计非常关键的一点就在于,根据用户与设备屏幕距离的不同,应用于设备屏幕的字体大小也应该不同。对于字体大小与阅读距离的关系,已经有计算的方法。

案例分析

请查看 moonbase 网站。这是一个帮助其他公司设计网站的网站。网页中央的文本十分显眼,它传达了这个站点的功能。我们只需看一眼就能明白。突出的字体能紧紧地抓住用户的注意力,并促使他们继续阅读网站的其余部分。

http://moonbase.co/

6. 响应式排版要求浏览器支持不同大小的字体

如果你设计的网页中需要用到某些自定义字体,你必须确保浏览器支持加载和显示这些字体。即便你的字体本身清晰,没有错误,但浏览器兼容问题可能会使你前功尽弃。你还必须检查你保存的字体文件格式与你想应用于网页中的字体是否兼容。不兼容的字体无法正常加载,最终会影响网页的显示。

案例分析:从上面的示例中我们可以发现,我们需要使用标准字体或“字体库”。第一步是通过“字体测试”来确定一款字体是否适用于网页中。浏览器对于每个系列的字体都有“第一选项”,“第二选项”,“第三选项”……的区分。如果浏览器在这个系列中赵爱不到任何合适的字体,它会自动选择默认的无衬线字体,衬线字体或Monospace字体。

举例来说,很多浏览器都自带 Century Gothic字体。你可以创建一个字体库,将Century Gothic字体视为你的第一选项,之后是Arial, Helvetica,最后是一款无衬线类的字体。注意,在CSS中,标题中含有多个单词的字体需要加上引号。例如: font-family:“Century Gothic”, Arial, Helvetica, Sans-Serif.

这样一来,浏览器会首先采用Century Gothic字体。由于很多浏览器都自带这款字体,多数用户在浏览网页时看到的也会是Century Gothic字体。对于没有配置 Century Gothic的浏览器,浏览器会按照Arial, Helvetica,事前设置的无衬线字体的顺序寻找替代。

7.与字体的物理属性相关的因素会影响字体在设计中的灵活度

响应式排版可能会受制于影响字形的因素。这些因素包括字重,字宽,笔画对比,字体高度,光学尺寸等等。这些因素的些微变化都会影响站点的观感。当然,现在已经有了不少的工具可以让设计师部分地修正这些限制。

Superpolator 和FlowType.js就是此类工具中有代表性的两款。当屏幕尺寸减小时,不同比例的网页间的差异就会更为凸显。因此就需要在网页尺寸与缩放比例间找到平衡点。例如,用于标题的字体比用于正文的字体大/小多少倍,这就涉及比例问题。这也就是我们为何需要响应式排版的理由。我们需要在断点中能自行缩小的字体,因为设计师们无法为网页内的所有字体元素一一调整基线风格。

案例分析

请查看flowtype网站。借助 Superpolator 和FlowType.js之类的工具,只需拖动滑块,你便能清楚地看到响应式排版的作用。

http://simplefocus.com/flowtype/

响应式排版的操作需要在实践中不断完善。通过对媒介查询(media queries)知识的学习和对不同屏幕尺寸的设备进行测试,你将会逐步掌握响应式排版的要点。现在你已经知道了要达到最好的响应式排版效果需遵循哪些原则,今后便可以将这些原则贯彻到自己的设计中。

改变CSS世界纵横规则的writing-mode属性

作者:张鑫旭(@张鑫旭)

链接:http://www.zhangxinxu.com/wordpress/2016/04/css-writing-mode/

一、冉冉升起的writing-mode

writing-mode这个CSS属性,我们是不是很少见到,很少用到!我们往往称不常见的东西为“生僻”,就像是不常见的文字我们叫“生僻字”,因此不常见的CSS属性,我们可以叫做“生僻属性”,writing-mode给我们的感觉就是一个“生僻属性”,很弱,可有可无。

但是,实际上,我们都错了,大错特错,writing-mode很弱?卧槽,别开玩笑了,writing-mode可以说是CSS世界里面最逆天的CSS属性了,直接颠覆CSS世界的众多规则。

而writing-mode之所以给人“生僻”的感觉,是有原因的。

实际上writing-mode这个CSS属性在上古时代就诞生了,IE5.5浏览器就已经支持了:

那就奇怪了!writing-mode既然这么鸟,同时时间早,资格老,为啥一直沉寂了差不多20年呢?

那是因为,在很长一段时间里,FireFox, Chrome这些现代浏览器都不支持writing-mode,writing-mode基本上就是IE浏览器的私有产物,大家对IE一直没啥好感,对吧,爱屋及乌由此及彼,自然对writing-mode也不待见。

然而,就在我们被流行前端技术一叶蔽目的时候,各大现代浏览器纷纷对writing-mode实现了更加标准的支持(主要得益于FireFox浏览器的积极跟进),也就是说,不知什么时候起,writing-mode的兼容性已经不成问题了,加上该属性本身特性逆天,我去,我仿佛看到了一个冉冉升起的新星,不对,是新月,而且是圆月。

二、writing-mode的原本作用

和float属性有些类似,writing-mode原本设计的是控制内联元素的显示的(即所谓的文本布局-Text Layout)。因为在亚洲,尤其像中国这样的东亚国家,存在文字的排版不是水平式的,而是垂直的,例如中国的古诗古文。

因此,writing-mode就是用来实现文字可以竖着呈现的。

您可以狠狠地点击这里:CSS writing-mode与文字垂直排版demo(http://www.zhangxinxu.com/study/201604/writing-mode-text-vertical-layout.html)

截自IE11浏览器IE8模式:

writing-mode语法

writing-mode的语法学习相比其他CSS属性要高一些,因为我们需要记住两套不同的语法。一个是IE私有属性,第二个是CSS3规范属性。

先看下未来所需的CSS3语法:

/* 关键字值 */

writingmode: horizontaltb;    /* 默认值 */

writingmode: verticalrl;

writingmode: verticallr;

 

/* 全局值-关键字inherit IE8+,initial和unset IE13才支持 */

writingmode: inherit;

writingmode: initial;

writingmode: unset;

各个关键字属性值的含义,我们透明名称就能知道其大概的意思,例如,默认值horizontal-tb表示,文本流是水平方向(horizontal)的,元素是从上往下(tb:top-bottom)堆叠的。

vertical-rl表示文本是垂直方向(vertical)展示,然后阅读的顺序是从右往左(rl:right-left),跟我们古诗的阅读顺序一致。

vertical-lr表示文本是垂直方向(vertical)展示,然后阅读的顺序还是默认的从左往右(lr:left-right),也就是仅仅是水平变垂直。

下面是各个值下的中英文表现对照(参考自MDN):

//zxx: 大家会发现英文字符横过来了,可以试试使用text-orientation:upright让其直立,IE不支持,FireFox, Chrome支持。

下面来看下老IE浏览器的语法,由于历史原因,显得相当的复杂,IE官方文档显示如下:

-ms-writing-mode: lr-tb | rl-tb | tb-rl | bt-rl | tb-lr | bt-lr | lr-bt | rl-bt | lr | rl | tb

根据自己的测试(非原生IE8,IE9),-ms-私有前缀是可缺省的,直接writing-mode所以IE浏览器都是支持的。-ms-writing-mode这种写法IE7浏览器是不支持的,但是官方有如下说明:

Windows Internet Explorer 7. The rl-tb, and bt-rl values are available to the -ms-writing-mode

就是说IE7的-ms-writing-mode可以使用rl-tb和bt-rl这两个值,但这和自己的测试不符,我觉得可能是原生IE7浏览器,但我没有原生IE7,没有进行过测试,因此,此说法(原生IE7支持)只是自己的推测。

我扳指头数了数,IE浏览器下的关键字值多达11个,正好可以组个足球队,

lr-tb

IE7+浏览器支持。初始值。内容从左往右(left-right),从上往下(top-bottom)水平流动,以及下一行水平元素在上一行元素的下面,所有符号都是直立定位。大部分的书写系统都是使用这种布局。

rl-tb

IE7+浏览器支持。内容从右往左(right-left,从上往下(top-bottom)水平流动,以及下一行水平元素在上一行元素的下面,所有符号都是直立定位。这种布局适合从右往左书写的语言,例如阿拉伯语,希伯来语,塔安那文,和叙利亚语。

tb-rl

IE7+浏览器支持。内容从上往下(top-bottom),从右往左(right-left)垂直流动, 下一个垂直行定位于前一个垂直行的左边,全角符号直立定位,非全角符号(也可以被称作窄拉丁文或者窄假名符号)顺时针方向旋转90°。这种布局多见于东亚排版。

bt-rl

IE7+浏览器支持。内容从下往上(bottom-top),从右往左(right-left)垂直流动, 下一个垂直行定位于前一个垂直行的左边,全角符号直立定位,非全角符号(也可以被称作窄拉丁文或者窄假名符号)顺时针方向旋转90°。此布局多见于在东亚垂直排版从右往左的文本块上。

tb-lr

IE8+浏览器支持。 内容从上往下(top-bottom),从左往右(left-right)垂直流动。下一个垂直行在前一个的右边。

bt-lr

IE8+浏览器支持。 内容从下往上(bottom-top),从左往右(left-right)垂直流动。

lr-bt

IE8+浏览器支持。 内容从下往上(bottom-top),从左往右(left-right)水平流动。下一个水平行在前一行的上面。

rl-bt

IE8+浏览器支持。内容从下往上(bottom-top), 从右往左(right-left)水平流动。

lr

IE9+浏览器支持。在SVG和HTML元素上使用。等同于lr-tb.

rl

IE9+浏览器支持。在SVG和HTML元素上使用。等同于rl-tb.

tb

IE9+浏览器支持。在SVG和HTML元素上使用。等同于tb-rl.

各个属性值的表现如下(form微软官网)

一些说明:

  • 相同的writing-mode属性值并不会累加,例如父子均设置了writing-mode:tb-rl,只会渲染一次,子元素并不会2次“旋转”。
  • IE浏览器下,一个自身具有布局的元素(不是纯文本之类元素)如果writing-mode属性值和父元素不同,当子元素的布局流变化的时候,其父元素坐标系统的可用空间会被充分利用。左边文字太过术语,大家可能不懂,我解释下就是,IE浏览器下,当布局元素从水平变成垂直的时候(举个例子),你就想象为元素在垂直方向是100%自适应父元素高度的。所以,IE浏览器下(不包括IE13+),元素vertical流的时候会发现高度高的吓人,布局和其他现代浏览器不一样,就是这个原因。
  • Chrome浏览器下目前还需要-webkit-私有前缀,虽然Chrome和Opera认识tb-rl等老的IE属性值,但是,仅仅是认识而已,根本不鸟,没有任何效果,聋子的耳朵——摆设!

需要关注的writing-mode属性值

从着眼于直接开发的角度而言,虽然IE支持多达11个私有的属性值,但是,我们需要关注的,也就那么几个,那究竟是哪几个呢?

如果你的项目需要兼容IE7,则只有关注这两个值就可以了:初始值lr-tb和tb-rl,对应于CSS3规范中的horizontal-tb和vertical-rl!其他9个属性值就让它们去过家家好了。

如果你的项目只需要兼容IE8+,恭喜你,你可以和CSS3规范属性完全对应上了,而且IE8下的writing-mode要比IE7强大的多。我们需要关注:初始值lr-tb, tb-rl以及tb-lr,分别对应于CSS3中的horizontal-tb, vertical-rl以及vertical-lr。

看上去复杂的属性是不是变得很简单了,重新整一个实战版:

writingmode: lrtb | tbrl | tblr (IE8+);

writingmode: horizontaltb | verticalrl | verticallr;

对,大家只要记住上面几个就可以了,enough! 因为所谓的垂直排版,实际web开发是很少很少遇到的。

有同学可能要疑问了,既然writing-mode实现文本垂直排版场景下,那还有什么学习的意义呢?

前面也提到了,虽然writing-mode创造的本意是文本布局,但是,其带来的文档流向的改变,不仅改变了我们多年来正常的CSS认知,同时可以巧妙实现很多意想不到的需求和效果。

三、writing-mode不经意改变了哪些规则?

writing-mode将页面默认的水平流改成了垂直流,颠覆了很多我们以往的认知,基于原本水平方向才适用的规则全部都可以在垂直方向适用!

1. 水平方向也能margin重叠

W3C文档margin重叠之一:

The bottom margin of an in-flow block-level element always collapses with the top margin of its next in-flow block-level sibling, unless that sibling has clearance.

清清楚楚写的bottom margin和top margin会重叠;然而,这是CSS2文档中的描述,在CSS3的世界中,由于writing-mode的存在,这种说法就不严谨了,应该是对立流方向的margin值会发生重叠。换句话说,如果元素是默认的水平流,则垂直margin会重叠;如果元素是垂直流,则水平margin会重叠。

您眼见为实,您可以狠狠地点击这里:CSS writing-mode与margin水平重叠demo

结果:

2. 可以使用margin:auto实现垂直居中

我们应该都是的,传统的web流中,margin设置auto值的时候,只有水平方向才会居中,因为默认width是100%自适应的,auto才有计算值可依,而垂直方向,height没有任何设置的时候高度绝不会自动和父级高度一致,因此,auto没有计算空间,于是无法实现垂直居中。但是,在writing-mode的世界里,纵横规则已经改变,元素的行为表现发生了翻天覆地的变化。

  • 图片元素

我们先来看下,图片元素margin:auto实现垂直居中,您可以狠狠地点击这里:CSS writing-mode与图片margin:auto垂直居中demo(http://www.zhangxinxu.com/study/201604/writing-mode-vertical-image-margin-auto.html)其中图片:

img { display: block; margintop: auto; marginbottom: auto; }

FireFox浏览器下(P白省流量):

但是,在IE浏览器下,却没有垂直居中~~

纳尼?!难道IE不支持垂直流下的垂直居中?非也,根据鄙人的测试,也就是图片这类替换元素貌似不行,普通的block元素都是可以的。

  • 普通块状元素

您可以狠狠地点击这里:CSS writing-mode与普通block元素margin:auto垂直居中demo(http://www.zhangxinxu.com/study/201604/writing-mode-vertical-margin-auto.html)此时,不仅IE11 edge,甚至IE8浏览器也都垂直居中了!IE8浏览器下block元素的margin:auto居中

3. 可以使用text-align:center实现图片垂直居中

前面提过,auto无法实现IE浏览器下的图片垂直居中,如果我们非要让图片垂直居中,可以使用text-align:center,您可以狠狠地点击这里:CSS writing-mode与图片text-align:center垂直居中demo(http://www.zhangxinxu.com/study/201604/writing-mode-vertical-image-text-align-center.html)

结果,之前病恹恹的IE浏览器活了:

由于我们直接使用内联特性进行控制的,因此,IE7浏览器也是可以实现text-align:center下的图片垂直居中,但是,根据我在IE11↘IE7下的测试,writing-mode需要写在最后重置下(原生估计不会这样),因此,完整的writing-mode代码为:

.verticlemode {

    writingmode: tbrl;

    –webkitwritingmode: verticalrl;      

    writingmode: verticalrl;

    *writingmode: tbrl;

}

4. 可以使用text-indent实现文字下沉效果

这是真实项目例子,要增加一个按钮按下文字下沉的效果。如果你来实现,你会这么实现呢?行高控制?但默认文本就不居中(对于高度自适应的按钮,line-height下沉为了避免按钮高度变化,默认是不能完全居中的)。padding+height精确控制,又略烦。然而,在writing-mode垂直流下,我们又有了新思路,例如,直接使用text-indent实现垂直方向的控制,没想到吧,无需关心height高度padding间距大小,任何按钮都可以通用,因为text-indent不会影响元素原本的盒布局。

您可以狠狠地点击这里:CSS writing-mode与text-indent文字下沉效果demo(http://www.zhangxinxu.com/study/201604/writing-mode-text-indent-vertical-down.html)

包括IE7在内的浏览器都是支持的(同上最后要*writing-mode覆盖下)都是支持下沉的。

为什么有如此的实现呢?这要归功于中文,在垂直流排版的时候,中文是不会旋转的,还是直立的,也就是说,虽然我们肉眼看上去文字没什么变化,但是,布局流已经发生了变化,以前类似text-indent/letter-spacing等水平控制属性都作用在垂直方向了。

当然,我们这个例子比较巧的是按钮文字只有一个,要是按钮文字有多个,怕是就没这么轻松和绝妙了。

5. 可以实现全兼容的icon fonts图标的旋转效果

在老的IE浏览器下,我们要实现小图标的旋转效果是不是很烦?要使用IE的旋转或翻转滤镜(filter)什么的,具体可参见我之前的“CSS垂直翻转/水平翻转提高web页面资源重用性”以及“IE矩阵滤镜Matrix旋转与缩放及结合transform的拓展”一文。

现在我们有了writing-mode,我们就不要这么烦心了。

前面可能也注意到了,当writing-mode把文档变成垂直流的时候,我们的英文和数字符号是会“躺着”显示,也就是天然90°旋转了。此时,我们不妨脑洞大开一下,假如我们使用icon fonts技术让这些字符直接映射某个小图标,那岂不是松松实现小图标旋转了,关键在于,就算是千年杀的IE6,IE7浏览器也是支持的啊,这要比滤镜什么的简单多了!

眼见为实,您可以狠狠地点击这里:writing-mode实现icon fonts图标旋转效果demo(http://www.zhangxinxu.com/study/201604/writing-mode-font-face-icon-rotate.html)

就算是IE7浏览器,也是很给力的!

6. 充分利用高度的高度自适应布局

卧槽,不行了,内容太多了

往下的7,8,9,10一起都略了吧~~

总之,放开自己的大脑,理论上讲,有了writing-mode,我们能够做的事情比以前多了50%,就怕你想不到,不怕做不到。

四、writing-mode和direction的关系

上个月刚刚介绍了CSS direction属性,也是个好东西,具体参见“CSS direction属性简介与实际应用”,其可以改变文字的走向,那他和writing-mode是个什么关系呢?

writing-mode, direction, unicode-bidi(MDN文档)是CSS世界中3大可以改变文本布局流向的属性。其中direction, unicode-bidi属于近亲,经常在一起使用,也是唯一两个不受CSS3 all属性影响的CSS属性,基本上就是和内联元素一起使用使用,且据说貌似为阿拉伯文字设计。

乍一看,writing-mode似乎包含了direction, unicode-bidi某些功能和行为,例如vertical-rl的rl和direction的rtl值有相似之处,都是从右往左。然而,实际上,两者是没有交集的。因为vertical-rl此时的文档流为垂直方向,rl表示水平方向,此时再设置direction:rtl,实际上值rtl改变的是垂直方向的内联元素的文本方向,一横一纵,没有交集。而且writing-mode可以对块状元素产生影响,直接改变了CSS世界的纵横规则,要比direction强大和鬼畜的多。且据说貌似为东亚文字设计。

然而,CSS的奇妙就在于,某些特性当初可能就是问了某些图文排版设计,但是,我们可以利用其带来的特性,发挥自己的创造力,实现其他很多意想不到的效果。所以,上面出现的三剑客都是非常好的资源。

五、writing-mode和*-start属性的流机制

CSS3中出现了诸多*-start/*-end属性(亦称为CSS逻辑属性),例如:margin-start/margin-end, border-start/border-end, padding-start/padding-end, 以及text-align:start/text-align:end声明。

下面问题来了,为什么会蹦出这么多*-start/*-end鬼?

那是因为现代浏览器加强了对流的支持,包括老江湖direction,以及最近年月跟进的writing-mode。

在很久以前,我们的认知里,网页布局就一种流向,就是从左往右,从上往下,因此,我们使用margin-left/margin-right没有任何问题。但是,如果我们流是可以变化的,例如,一张图片距离左边缘20像素,我们希望其文档流是从右往左,同时距离右侧是20像素,怎么办?

此时,margin-left:20px在图片direction变化后,就无效了;但是,margin-start就不会有此问题,所谓start, 指的是文档流开始的方向,换句话说,如果页面是默认的文档流,则margin-start等同于margin-left,如果是水平从右往左文档流,则margin-start等同于margin-right。margin-end也是类似的。

webkit内核的浏览器还支持*-before和*-end,默认流下的margin-before近似于margin-top,margin-after近似于margin-bottom,然而,规范貌似没提及,FireFox也没支持,*-before和*-after出场的机会并不多,为什么呢?因为实际上,配合writing-mode,*-start/*-end已经可以满足我们对逻辑位置的需求了,水平和垂直都可以控制,对立方向适用老的*-top/*-bottom.

例如,我们设置writing-mode值为vertical-rl,此时margin-start等同于margin-top,如果此时margin-start,margin-top同时存在,会遵循权重和后来居上原则进行相互的覆盖。

可以看到,场景不同,margin-start的作用也不能,能上能下,能左能右简直在世百变星君。

关于*-start/*-end以后有机会会具体展开论述,这里就先点到为止,大家估计目前也不会在实际项目中使用。

这可能是史上最全的CSS自适应布局总结

作者:茄果

链接:http://www.cnblogs.com/qieguo/p/5421252.html

标题严格遵守了新广告法,你再不爽,我也没犯法呀!屁话不多说,直入!

所谓布局,其实包含两个含义:尺寸与定位。也就是说,所有与尺寸和定位相关的属性,都可以用来布局。

大体上,布局中会用到的有:尺寸相关的盒子模型,普通流、浮动、绝对定位三种定位机制,CSS3中的transform、弹性盒子模块、试验中的grid模块。逛园子的时候经常可以看到浮动布局,inline-block布局,弹性盒布局这几个名词。现在对布局也算有一点了解,做个总结巩固一下。如果你也看了很多资料,但是实际动手时对布局还是无从下手的话,希望本文可以帮你理清思路。

唠叨一句:看到一个效果图的时候,千万不要急着手贱去敲代码!先思考清楚页面的构造,理清各元素之间的关系,特别需要注意的是在不同的设备下需要有怎样的展现,当你思路清晰找到最好的布局方案时,coding其实真的不需要多少时间。

尺寸相关

为什么要先说尺寸呢?因为尺寸在布局中的作用非常核心,布局方式定位这些只是改变了元素之间的关系,没有尺寸就什么也不是。比如我们通常会用margin来控制跟其他元素的距离,这就是布局。

很多人都会觉得,什么width、margin太简单了,早就掌握了。这种心态我一开始学习CSS的时候也有,觉得很好理解很简单,但是后面才发现自己原来很多东西都没真正掌握。看看张鑫旭大神给我们上的政治课:http://www.zhangxinxu.com/wordpress/2012/07/bottleneck-css-study/

先说说百分比,百分比是相对父对象的,这里特性非常好用,很多时候会用在自适应布局上面。浏览器尺寸的改变,就是根节点html的长宽改变,我们可以用%来将浏览器尺寸和元素尺寸联系起来,做到自适应。

另外一个比较有意思的是auto,auto是很多尺寸值的默认值,也就是由浏览器自动计算。首先是块级元素水平方向的auto,块级元素的margin、border、padding以及content宽度之和等于父元素width。使用auto属性在父元素宽度变化的时候,该元素的宽度也会随之变化。

但是当该元素被设为浮动时,该元素的width就变成了内容的宽度了,由内容撑开,也就是所谓的有了包裹性。overflow | position:absolute | float:left/right都可以产生包裹性,替换元素也同样具有包裹性。在具有包裹性的元素上想利用width : auto;来让元素宽度自适应浏览器宽是不行的。

高度方向:外边距重叠,外边距auto为0,这两点需要注意。书写方向什么的,接触比较少就不扯了。

那为什么margin:auto对不能计算垂直方向的值呢?很简单,垂直方向是被设计成可以无限扩展的,内容越多浏览器便产生滚动条来扩展,所以垂直方向都找不到一个计算基准,以此返回一个false,便成了0。

用处:通过width、height控制大小,各个方向的margin值控制与边界或者其他元素的距离来定位。

浮动

目前PC网站大多使用float布局,从成本上考虑大改的概率很小,所以不要说浮动无用,总是会有机会让你维护的!代表网站:淘宝、腾讯、百度,好吧BAT都到齐了。

浮动听得多了,博客园上关于用浮动布局的介绍也非常的多。浮动原本用于文本环绕,但却在布局被发扬光大,这就是命!我的理解:浮动布局的核心就是让元素脱离普通流,然后使用width/height,margin/padding将元素定位。脱离普通流的元素,就像脱离地心引力一样,与普通流不在一个高度上。这个跟图层的概念类似。高度不同所以可以叠在其他元素上面产生重叠或者使用负边距跑到父元素外,理解了这一点浮动布局就很好理解了。

下面用个圣杯布局的例子说明一下,理解了这个之后其他布局更加简单:

left,宽度固定,高度可固定也可由内容撑开

right,宽度固定,高度可固定也可由内容撑开

center,可以自适应浏览器宽度,高度可固定也可由内容撑开。

HTML & CSS:

原理非常简单,左右侧边栏定宽并浮动,中部内容区放最后不浮动、默认width:auto并设置相应外边距,让左右侧边栏浮动到上面。注意:子元素设置为浮动之后,父对象的高度就坍塌了,需要设置父对象后的元素清除浮动,这样父对象的高度才能被浮动子元素撑起来了。

当然,我们也要问一下,为啥父对象高度会坍塌呢?上面也说过了,浮动元素已经脱离了普通流,父对象所在的普通流比喻成地表,那浮动元素就已经上天了。但是父对象还在地表啊,从外太空看浮动元素在父对象里面,但是其实并不在,又怎么能撑开父对象呢?宽度如果我们不设置的话,其实也是为0的,因为父对象里面空空如也,所以宽高为0。

要撑开的办法就两个,1是让父对象也上天(。。。你咋不上天呢),2是把浮动元素的边框边界拉下来。

父对象也上天(即浮动)的话,那就不能实现宽度自适应了。因为float元素的width:auto是包裹内容的,参考前面说的!

办法2就是在后面的元素里加一个clear语句。说到这个问题就要扯到clear与BFC了,我就不献丑了。传送门:https://developer.mozilla.org/zh-CN/docs/Web/CSS/clear

这个三列布局还有个双飞(是双飞翼!想啥呢)的变种,就是在HTML中center部分也就是内容区提到最前面,也就是内容先行渲染。在网络不好的时候,左右双翼能不能出来不要紧,先让主体内容出来!这种想法,明显的优秀工程师思维,但,尼玛的双翼都是广告啊。广告不出来,哪能赚钱养你们这群工程师?所以提出双飞的玉伯才离开了淘宝???(纯属意淫,如真属实,当我扯淡,哈哈哈!)

先上码:

思路:

1)既然HTML里面要让center放前面,为了让left跑到center前面,那center也必须浮动了,否则因为都是块元素他们会分两行。

2)浮动之后还要让center宽度自适应,那明显width只能100%,然后在父元素中设width:auto,还有两侧margin,其实也就是父对象宽度自适应,center只是继承content的宽度。

3)对left使用负的margin让他们浮动到上方去。

代码里面我用到了一个calc(),这个CSS3带来的计算函数简直酷毙了!本例里如果不使用calc函数,那么就需要wrap左边距为0,left左边距-100%,然后center多加一层子块DIV设置margin-left:100px,可以达到同样的效果!calc函数与百分比配合就足以实现自适应的要求!目前所有的自适应布局都在利用浏览器来为我们计算尺寸,但是有了calc之后我们就可以自己制定规则!单是想想都高潮了吧?

总结:使用浮动来进行布局,一个比较大的问题是清除浮动。这个可以使用一个after伪类来清除。更大的问题是浮动性像水一样向上流动,难以把握。在元素较多而且元素高度尺寸不一的情况下,单纯使用浮动只能实现上端对齐,这对于适应多种设备的布局就显得力不从心了。目前的做法是牺牲一部分内容,将元素做成等高排列,从美观上看也当然也是极好的,比参差不齐的排列要美观。

普通流布局

普通流布局:display : inline-block!这是一个传说中取代float布局的存在。看了一些网站,PC端浮动为主,移动端的也用的不多啊,已经有些使用flex的了,说好的inline-block一统江湖呢?

使用inline-block之前先处理点小障碍:inline-block元素会有4px左右的空隙,这个是因为我们写代码时候的换行符所致。

解决办法很简单:在inline-block的父元素中设置样式font-size:0;letter-spacing: -4px; 然后设置inline-block的所有兄弟元素 font-size:值;letter-spacing: 值px;  恢复正常的显示。

另外还有一点需要注意的是inline-block默认是基线对齐的,而inline-block的基线又跟文本基线一致,所以在内容不同的时候并不能水平对齐。只需要用vertical-align显式声明一下top/bottom/middle对齐即可。这里补充一下基线的内容,没你想的那么简单哦。分有文字和无文字两种情况:

1)无文字:容器的margin-bottom下边缘。与容器内部的元素没一毛钱关系。

2)有文字:最后一行文字的下边缘,跟文字块(p,h等)的margin、padding没关系!注意是最后一行,无论文字在什么子对象容器内在什么位置都没关系,浏览器会找到最后一行文字对齐底部。

你们感受一下:

警示:inline-block的基线是最后一行文字的底部,flex里面的基线是第一行文字的底部(请看下文阮老师的文章)

满满的都是泪啊。。。既然都叫baseline,何必呢?

使用inline-block进行圣杯布局:

这里也没什么好说的,用到的也是width:auto和width:100%这两点,简单知识点的简单用法。

双飞的话,代码跟圣杯的基本相同,注意在html的顺序变为center>right>left,只改左栏移动的margin-left: calc(-100% – 100px)到预定位置即可。不能用calc的话可以在center里面再加一层,跟浮动一样的处理方式。更简单的方法是使用CSS3带给我们的box-sizing属性。请看代码:

总结:相比浮动inline-block更加容易理解,也更符合我们的认知,结合盒子模型的几个控制属性就可以进行布局了。对于元素高度不同的情况,目前浮动布局的做法都是将元素做成等高元素进行展现,这从美学上看也符合整齐的要求,不过牺牲了一部分内容。但inline-block有vertical-align属性,可以很好地解决元素高度不同而带来的布局问题。用过之后,你也会喜欢上inline-block的。。。至少我会!

绝对定位

前面的浮动和普通流中其实定位都是靠盒子模型控制的,与我们常说的定位还是有差别的。而绝对定位就是我们平常所说的定位,给定参考坐标系+坐标确定位置。关于绝对定位的资料太多,我就不说了。提一点就是absolute定位的基准是最近的非static定位父对象,而fixed是相对html根节点的定位。两种定位都会脱离普通流,跟之前说的浮动一样,上天了。

当然,他们跟浮动在空间中的位置还是有差别的,项目中有遇到这个问题的请参考张大婶的文章: http://www.zhangxinxu.com/wordpress/2016/01/understand-css-stacking-context-order-z-index/  还是要结合项目来看,否则看过也只是看过而已,并不会存到你的脑子里,毕竟还是相当抽象相当理论性的东西。借用张大神的一个总结图:

使用绝对定位(特指absolute)做自适应布局跟前面两种方式没太大差别,宽度自适应还是在auto和100%上做文章,而位置则由top/bottom/left/right等控制。还是以圣杯布局来举例:

<!DOCTYPE html>

<html>

    <head>

        <meta charset=“utf-8” />

        <title>宽度自适应布局</title>

        <style>

            .wrap {

                position: relative;

                background-color: #FBD570;

                margin-left: 100px;

                margin-right: 150px;

                height: 250px;

            }

            .left {

                position: absolute;

                top: 0;

                left: -100px;

                width: 100px;

                background: #00f;

                height: 180px;

            }

            .right {

                position: absolute;

                top: 0;

                right: 0;

                   width: 150px;

                background: #0f0;

                height: 200px;

                margin-right: -150px;

            }

            .center {

                position: absolute;

                top: 0;

                left: 0;

                background: #B373DA;

                height: 150px;

                min-width: 150px;

                width: 100%;

            }

        </style>

    </head>

    <body>

        <div class=“wrap”>

            <div class=“center”>

                center,可以自适应浏览器宽度,高度固定。

            </div>

            <div class=“left”>left,宽度高度固定</div>

            <div class=“right”>right,宽度高度固定</div>

        </div>

    </body>

</html>

父元素为relative,子元素为absolute,这样的话,又会出现跟浮动一样的问题:父对象高度坍塌,子元素不能撑起父对象。原因也跟浮动一样,解决办法的话目前我知道的只有给父对象指定一个确定height值,大家如果有更好的办法,请联系我!

总结:单纯使用绝对定位进行自适应布局的情况很少,一般绝对定位都用在尺寸固定的元素定位上。而且fixed定位的渲染效率很低,因为它会频繁触发浏览器的重排。另外提一点:CSS3的transform会对绝对定位产生影响哦~比如说让fixed定位不再固定在浏览器视窗的黑魔法:http://www.zhangxinxu.com/wordpress/2015/05/css3-transform-affect/

弹性盒子

CSS3中对布局影响最大的莫过于弹性盒子模块了,这是一套区别于以往盒子模型布局的全新方案。上面几种方法你可以看到,为了实现自适应我们用的都是width:auto和100%的嵌套以及各种边距的移动定位,这套规则并不符合我们的认知。为什么不能开拓出一块区域,横竖排列都可以,内部所有元素的尺寸可以按照一个规则和这个区域的大小联系起来?终于CSS3做出了改变,引入了flex弹性布局方案,弹性盒布局有如下优势:

1.独立的高度控制与对齐。

2.独立的元素顺序。

3.指定元素之间的关系。

4.灵活的尺寸与对齐方式。

在MDN上有非常简单易懂的基础教程:https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_Flexible_Box_Layout/Using_CSS_flexible_boxes

上面也已经给出了圣杯布局的自适应布局方案,所以代码就不贴了不过这个例子实现的是3栏成比例缩放,左右栏如果需要固定值的话可以写成  flex: 0 0 150px; 的样式。

但是上面的教程没有给出各个属性的详细解释,建议看看阮一峰的博文,详细易懂而且配图超漂亮的有木有:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

总结:弹性盒子在移动端的应用会越来越普遍,这套模型值得去好好研究。语法规则都是非常贴近人性,非常灵活,浏览器兼容性也非常好,当然国内百花齐放的移动浏览器会有哪些大坑呢?我们拭目以待~

其他

其他包括position:relative和CSS3中的transform都可以实现定位,但是由于他们在原来的普通流中还占着一个坑,所以很少用来布局啥的。transform是个很酷炫的东西,可以用平面的素材做出很多3D的效果,而且不需要js就可以做,非常好玩。此文已经很长,就不多说了,以后会写一篇文章来专门说说她的故事。

小公司的前端应该怎么做?

作者:叶小钗(@欲苍穹)

链接:http://www.cnblogs.com/yexiaochai/p/5311712.html

前言

近期工作生活比较漂泊,从上海换到了成都,这个是以家庭为单位的重大决定,离开一线城市对于职业生涯和技术前沿来说是有一定问题的,但是出于房价考虑(主要是买不起房子)与生活舒适度来说,回蓉似乎是一个比较好的选择,何况成都的互联网也还行。

随着能力的提升,负责的工作种类会逐渐增多,考虑的方向也会有所不同,这个时候不太会有太多单独的知识点成为阻碍了,工作中碰到的问题要么太“大”,总结起来费力,要么太“小”,不适合单独整理成文,这种现象反而造成了一段时期的博客空白期,总的来说就是又开始懒了,思维又开始懈怠,人又开始想待在安逸区了。

因为开始懒了,所以没能学习到新知识,自然出不了新文;因为开始懒了不愿意再对工作中的问题一个个深入研究、深入挖掘自然出不了新文。

所以人还是得不停的鞭笞自己啊,不能让自己陷入“瞎忙”的境地,得有效的利用时间,才能走的更远!!!

现在我在一家小公司做前端,因为公司以及职位的变化,对于在小公司如何做前端有一些心得,拿出来与各位做个分享,希望对处于小公司的前端有一定用处,也鞭笞自己重新学习总结。

什么是优秀的前端团队?

团队初期缺什么

在公司中,层级越高对业务关注比例越高,反而不太关注个人成长,所以评价一个leader是以团队为单位,团队成员比他强是应该的;对于个人来说的话,要多关注自身能力成长,然后能力匹配自己的职位,甚至超出自己的职位,这样的团队的话,战斗力是比较强的。

主管(包括前端主管)设定目标必须可量化 ,比如你做一个业务,kpi是多少,那么技术就需要考虑如何才能达成,细化到研发甚至前端层级,就是所谓技术kpi了。

比如,今年H5站想达到单日平均出票量10000,那么这个就是业务目标,需要消化分到各个业务团队,可以是:

① SEO优化

② SEM优化

③ 营销广告

④ 微信&支付宝&手机百度流量接入(微信钱包是十分优秀的流量入口,可以极大程度的增加流量)

⑤ 实地推广

……

以上当然只能解决部分问题,具体到前端,可能我们就要从页面转换率入手,建立订单漏斗模型,做性能优化,做交互优化,每一个具体的层面都需要转化目标。

这些都是直接可量化的东西,因为当前业务已经到了一个瓶颈,或者公司已经到了一个瓶颈,业务上就需要做不停的尝试,对应到技术就是需要你快速迭代,低成本迭代,不断的容错试错。

这个时候就会提出很多问题:

第一是你的团队在类似高压下会不会主动加班去实现公司的目标、个人的kpi。

第二是你的团队在这轮高压拼搏后有没有留下什么东西?

根据之前经验,没有团队可以无休止的承受高压加班的压力

以之前携程无线高压迭代的经历来说,就算是那么优秀的团队事实上到后期也是疲惫不堪,疲惫的时候容易犯错,亢龙有悔,盈不可久。

第三是如何帮助新人快速的融入团队,如何让1+1=2。

我们都清楚,好的项目绝不是堆人可以堆出来的,如何让一个项目可以分解到各个人手中,如何让良莠不齐的同事可以更好的协作,这个是我们需要考虑的。

要解决这些问题是要靠平时的积累,具体体现到前端是:

1 在不停的迭代中,你的业务流程是不是最优(产品到设计到前端到最终上线流程)

2 在不停的迭代中,是否沉淀出来了公共服务与工具化服务

好的前端是什么样的

首先,好的前端是一定愿意加班的,同时,好的前端是会找办法让团队少加班的。

和一些朋友做过交流,很多好的点子,改善工作效率的点子都是几个人讨论后私下晚上搞出来,然后反复实践用于生产的。

一般来说业务kpi对于能力强的朋友来说不会太难,所以对他们的期待也会更多:

有强烈的意识,能深刻了解到当前项目性能的缺陷,开发效率低下的原因,并会找寻处理办法

很多团队在快速迭代中会开始“欠账”,时间久了就不愿意还,问题的存在搁置需要想办法去解决,团队成员是看得到问题的,没人说,没人做是因为知道那是坑,你如果能解决的话,一到二次便能提升自己在团队中的位置。

好的前端应该有良好的架构设计能力

首先,好的前端能向人清晰有条理的描述自己的技术方案,并且让人听得懂!

然后架构设计能满足长久的需求发展,就算业务频道扩大了10倍,用户量增加了100倍,也不会有根本的变动。

好的前端应该具有良好的交流能力

对内,好的前端需要了解团队成员的性格与能力,做出适当的任务分配分解;对外,需要抢占业务还不能产生利益冲突,这类人是项目推进的主力。

小公司的前端应该怎么做

不是所有的小公司都这样,但是我见过的小公司的前端都在扑业务,并且疲于奔命,这个是个恶性循环,第一次做业务:

加班赶业务-业务结束轻松一周-加班赶迭代-业务结束轻松一周-加班新业务-业务结束轻松下……

偶尔你会问这些朋友为什么没有什么积累,得到的答案基本是一致的,忙啊!他们忙起来的时候是真的很忙,但是第二次如果依旧这么忙的话就有问题,第三次还这样就是团队不健康了,一个好的做法是:

① 完成前后分离,这步做不到,后面也不用做了

② 形成几套UI库

③ 根据业务形态,形成公共业务

④ 前端重复工作工具化

⑤ 形成优化体系

⑥ 形成统计体系

⑦ 建立页面转化漏斗模型

⑧ 做ABTesting方案

……

首先,无论出于什么考虑,前后一定要做分离,如果有SEO需求,那么再后续推进nodeJS方案,毕竟现在不给钱想排前面还是很难,SEO基本没意义。

其实,小公司有很多坑可以占住,这个会帮助你建立团队威望,下面我举几个细节点说一说。

UI库

UI库的形成与UI库的多少将决定你后续项目重复工作量的多少,这个UI库需要注意几点:

① UI是否可重用

② UI是否可定制

比如让很多朋友去做这个时间选择器,做出来就真的是时间选择器,如果让他换成城市选择器,就全傻眼了:

③ UI是否可拆分,可聚合

还是以上面UI为例,这个组件事实上是一个聚合组件,由一个select组件与一个弹出层组件组成,你的UI是不是可拆分是评价他质量的一个很大考虑点。

……

公共服务

公共服务可以说成一个大一点的“UI组件”,但是他是与业务相关的,UI来说一般不会与业务产生耦合,以上面的日期选择器来说,无论他装的是日期还是区域都是可以的,并且不应该请求服务,他是纯净的UI组件。

而公共服务是不纯净的是一定与业务相关的,移动端比较常见的公共服务是:

passport

包含登录注册、个人资料管理,甚至包含一些认证相关的,与公司账号相关的操作,登录注册是各种活动,各种业务频道都可能会使用的业务,这种东西是必须服务化的,但是很多小公司都没做。

因为公共的特点,页面设计最好中性一点,其中几个常用的页面,比如登录需要包含以下设计:

① 样式可定制化(弹出层、独立页面什么的都是常事)

② 回退可定制,其实所有的公共服务回退按钮都是需要定制的,登录成功去哪个URL登录失败去哪个URL,点击浏览器回退去哪个URL都得约定,少一个都不是公共服务

③ 单点登录,事实上初期根本用不到什么单点登录,甚至大家都不是跨域的,所以后续需要再支持即可

还有很多与passport一样的公共业务,比如:

① 钱包服务,包括用户支付订单相关管理

② 城市列表,这个要考虑参数如何传递

③ 反馈系统

④ 公司介绍

除了面向C端的公共页面服务,还会有面向B端的统计平台相关。

前端工具化

静态资源处理

评价一个前端团队是否优秀成熟的评判多以团队工具化的程度,一个简单的例子是:

① 你们前端静态资源是如何组织的、如何打包的

② 你们前端静态资源是如何解决缓存的(比较好的方案是MD5)

上面两点可以使用grunt/gulp一类的构建工具轻松做到,如果有公共框架文件还会需要引入种子文件的概念

跨域问题

另外,所有前端团队都会遇到跨域问题,特别是前后分离后,服务器端只提供API接口,前端代码随便在哪都能运行,那么这个时候你是怎么做呢?

① 使用fiddler&charles做代理

② 提供测试服务器

③ 支持jsonp跨域

④ 支持cors跨域

那么这些方案,哪种最适合团队,哪种成本最低(一般来说是代理),是我们需要考虑的

tips:我之前使用fiddler,现在换mac了使用charles,两款工具十分优秀,正则一块的处理很好,推荐使用

移动端适配

从后端转到前端的同学一般在业务逻辑上有一些天生的优势,但是往往在CSS一块比较弱,如何在开发人员无感的情况下引入rem,如何与现有机制无缝的使用less,如何处理单页应用中css的污染,这个是框架底层需要考虑的。

模块化&组件化开发

团队上规模后,如何使用模块化开发处理协作问题;业务代码复杂度上升后,如何使用组件化编程思维简单开发复杂度,这些需要应用到项目实践中,并且路径是可复制的;

一些优化手段,也需要工具化,框架化,让开发人员无感。

前后端协作

前端与服务器端,开发速度未必同步,事实上很多时候都不是同步的,在已经约定了接口格式的情况下,接口还没有写好,但是前端依然能写交互,团队是如何写这种假数据,这个方面实现会大大的提升工作效率。

订单下降分析

如果在某一个时间段,全站的流量或者全站的订单量下降了,你如何跟踪这次下降的原因,如何最大程度上避免下次出现类似的现象,这个时候数据统计会避免我们成为瞎子,所以得尽快建立统计平台,转换率模型。

快速迭代,通过迭代来优化产品,但是如果每一个迭代都完全颠覆了之前的设计,很多时候公司就是原地踏步,每迈出一步你要清晰的知道前一个版本哪里出了问题,针对问题做优化,而不是频繁改版。

这次改版后,你如何知道这次优化就比上一次的好,而不是其它因素造成,ABTesting方案应该是每一个成熟团队必须的,持续优化这些都是建立在有效的数据监控与意见反馈机制上的,我们不能做完网站变成瞎子。

结语

因为很久没有写博客了,又因为最近刚好来到了小团队,有一些想法以水文的形式发出来与各位讨论,希望对各位有用。

诚然,对于一个前端来说,要推动上述工作还是有一点难度的,但并不是不可能,前端对自己的定位要变,从前端工程师到软件工程师。

我常常听到很多前端自己都在质疑自己,或者就是膨胀到觉得自己团队没有什么可以做了,那么这个时候可以考虑下:

你们团队的自动化、安全性已经到位了吗,效率就真的完全没有上升空间了?

前端的重视程度需要你我一并努力,在大公司做前端难,在小公司做前端更难,你我共勉,最后补充下为什么回成都,以及回来的一些感受。

从一线城市到二线城市

几年前,怀着想学点新东西的想法,我来到了上海,在这边也确实学到了很多东西,关于学习有几个必要条件:

① 好的项目

② 好的团队

③ 加班总结

很多时候不是一些朋友不努力,但是PV上亿的项目国内真的不多,创业团队这种机会就更少,所以根本没有这种机会,这个时候看人家做的很多优化就是看热闹,似乎懂得了什么,其实什么都没懂。

就算是携程最好的时光,依旧有很多团队没有跟上好时候,比如不在无线的团队,那么无线团队的经验包,如果不是真正好学的人是接收不了的,就算我处于无线团队,native团队中很多经验包都是遗漏状态,而且无论怎么打听都是打听不出来的,就比如native资源更新机制,我就前前后后关注了两年,从各处零碎的得到了很多知识,现在看来依旧不够系统,不可谓不遗憾。

又比如有一次携程全站出现了一个重大BUG,因为是server端的问题,自己当时目光短浅没有去深入,到现在想深入都没有案例了,只能说机会稍纵即逝啊!!

所以就算后来进入百度了解到了fis的好,但是真正想去深入的话怎么都摸不着门道,只能学习一些思想走;这个也是一个框架成型后如果后面的人来维护怎么都维护不好的原因,因为他们找不着精髓,后来的人甚至会喷框架的各种不好,自己却找不出方案。

这个就是一线城市的一大好处:

一线城市,具有好项目(PV过亿),好团队的机会要好很多,只要你努力上进,就能收获很大的经验包。

这就意味着,只要你愿意学,就一定可以收获很大的经验礼包,这里有很多热心的大神,愿意与你讨论,愿意与你分享,而你的分享也会带给你快乐与成就感。

另外,外面的薪酬包也要比二线城市大得多,就我而言,回成都薪酬包只有原来的70%不到,如果这次没回成都的话,待遇应该会有长足的涨幅,但是最后还是选择的归蓉。

关于机会好的伪命题

很多人到一线城市打拼是觉得那里机会好,事实上这是一个伪命题(在我看来),不可否认沿海的机会很多,但真心说不上好。

职场这个东西真心不好说,你能力强需要人赏识你,你上去了还得你的老板上去,你老板上去了,还得你老板的老板也上去了,如果中间有一个老板失势了,那么新的老板可能会洗牌,情况好的话你留下,并且依旧令人尊敬,但是更多的情况是可能你得卷铺盖走人,互联网离职率高不是开玩笑的。

能力强不等于职位高,因为一般来说你的能力还没有那么强,能玩转公司的毕竟是少数,搞技术的更多的情况还是比较实在,想安安静静写代码,很少搞政治斗争,又心高气傲,又比较脆弱,面对不合理的KPI,或者被产品无限制的坑,是非常容易离职的。

外面优秀的人扎堆,所以真的机会只是相对的,你如果抱着学习收获经验包的想法出来会收获很大,如果你经验包已经够了,想更往上发展,那么这个是很难的,因为管理或者交流未必是开发擅长的。

再往上会关注业务发展,关注KPI,需要大量的产品知识,自己甚至会成为产品,这个时候搞技术的时间就会相对变少,但技术不好又很难让技术员工服众,光是技术好又上不去,竟然有点矛盾。

我身边就有几个人出去做CTO,结果团队刚刚上轨道就被扫地出门了……

另外,就是外面leader很辛苦,特别是团队上升期,好的leader会陪着团队加班,会很晚,我们之前好的老板(35岁左右)都是陪着团队加班的,总之钱不好赚,如果leader偷懒,几年下来可能会废掉,被淘汰掉,这个中年危机是不可忽视的。

虽然如此,一线城市的机会和成功的几率依旧比二线城市好得多,而你愿意拼搏,善于思考,是可以发展的很好的,那么我们为什么要去二线城市呢?

为什么去二线

去二线城市主要原因就是房价贵,房价太贵,同样的钱可以在成都买三套房子了,而且一线城市买的房子很偏远,上班得一个多小时,下班又得一个多小时,这样来说是相当令人疲惫的。

然后外面工作节奏太紧张,甚至已经紧张到没有生活了,有追求的人995是常态,996也是有可能的,这个会不断的透支你的身体,年轻点还好,稍微上点年纪,有了家庭的话就不行了,会考虑的更多了。

比如在一线城市落户的条件比较苛刻,小孩教育问题、父母养老问题都是你需要考虑的,想着想着,就会有一个想法,要不回老家算了,又不是找不到工作,于是就回来了。。。。。。

回成都后的感觉

回成都后,第二天便出差去北京,整个清明节都在加班,完了回成都也一直在加班,尼玛这边的工作强度一点也不比一线城市低啊!!!

但是,周末可以过得很惬意,一个月老妈也会来一次做些好吃的给我们吃,这种幸福感和归属感是外面没有的。

今天,我8点就下班,在软件园区信步而走,走了10多分钟,然后坐着公交车20分钟回家了,这种感觉还是很不错的。。。。。。

二线城市依旧会面临外面的各种挑战,不想面对依旧上不去,在哪都是面对,那就回老家面对咯。。。。。。

WEB请求处理(2):Nginx请求反向代理

陶邦仁

http://blog.jobbole.com/100526/

上一篇《WEB请求处理一:浏览器请求发起处理》,我们讲述了浏览器端请求发起过程,通过DNS域名解析服务器IP,并建立TCP连接,发送HTTP请求。本文讲述请求到达反向代理服务器的一个处理过程,比如:在Nginx中请求的处理流程,请求都是经过了哪些模块,做了哪些处理,又是如何找到应用服务器呢?

为直观明了,先上一张图,红色部分为本章所述模块:

Nginx有五大优点:模块化、事件驱动、异步、非阻塞、多进程单线程。其中,模块化设计类似于面向对象中的接口类,它增强了nginx源码的可读性、可扩充性和可维护性。

Nginx由内核和模块组成的,其中内核完成的工作比较简单,仅仅通过查找配置文件将客户端请求映射到一个location block,然后又将这个location block中所配置的每个指令将会启动不同的模块去完成相应的工作

所以,在讲述Nginx请求处理过程,首先要了解Nginx模块结构与功能,Nginx中有哪些模块,其功能又是如何。

1 Nginx模块

Nginx总共有5大一类模块:core、conf、event、http、mail,和48个二类模块每个模块有属于自己的配置项,由commands字段决定;每个模块在初始化和退出销毁时均有回调函数

多进程模式下的模块初始化主要有四个方面:脚本初始化、静态初始化、动态初始化、进程初始化

脚本初始化是指在安装nginx时,由configure脚本生成的相关文件,比如ngx_modules.c文件包含了nginx的所有模块;

静态初始化在编译时就完成,主要通过定义全局变量实现;

动态初始化在运行时完成,主要通过master进程main函数,ngx_init_cycle函数,及各模块文件内定义的init函数实现;

进程初始化是指各worker进程执行init_process函数。当nginx退出或重读配置文件或nginx平滑升级时,worker进程会调用各模块的exit_process函数来销毁资源。

开发人员可以根据nginx模块规则注册自己的模块,添加模块后要重新编译源码,并且修改nginx.conf配置文件才能使新模块生效。

1.1 四种角色模块

Nginx模块主要有4种角色:

(1) core(核心模块):构建nginx基础服务、管理其他模块;

(2) handlers(处理模块):用于处理HTTP请求,然后产生输出。

(3) filters(过滤模块):过滤handler产生的输出。

(4) load-balancers(负载均衡模块):当有多于一台的后端备选服务器时,选择一台转发HTTP请求。

Nginx的核心模块主要负责建立nginx服务模型、管理网络层和应用层协议、以及启动针对特定应用的一系列候选模块。其他模块负责分配给web服务器的实际工作:

(1) 当Nginx发送文件或者转发请求到其他服务器,由handlers(处理模块)或load-balancers(负载均衡模块)提供服务;

(2) 当需要Nginx把输出压缩或者在服务端加一些东西,由filters(过滤模块)提供服务。

1.2 模块结构设计

点击查看大图

点击查看大图

 

1.3 模块数据结构

  1. 核心:ngx_module_t(nginx所有模块的数据结构模板)
  2. 配置文件指令:ngx_command_t(主要负责模块与配置文件nginx.conf的交互)
  3. 指令配置:ngx_conf_t(解析某个具体的指令)
  4. 全局配置:ngx_cycle_t(nginx绝大部分初始化操作都围绕该结构体)

1.4 模块调用流程

  1. 当服务器启动,每个handlers(处理模块)都有机会映射到配置文件中定义的特定位置(location);如果有多个handlers(处理模块)映射到特定位置时,只有一个会“赢”(说明配置文件有冲突项,应该避免发生)。处理模块以三种形式返回:

    OK

    ERROR

    或者放弃处理这个请求而让默认处理模块来处理(主要是用来处理一些静态文件,事实上如果是位置正确而真实的静态文件,默认的处理模块会抢先处理)。

  2. 如果handlers(处理模块)把请求反向代理到后端的服务器,就变成另外一类的模块:load-balancers(负载均衡模块)。负载均衡模块的配置中有一组后端服务器,当一个HTTP请求过来时,它决定哪台服务器应当获得这个请求。Nginx的负载均衡模块采用两种方法:

    轮转法,它处理请求就像纸牌游戏一样从头到尾分发;

    IP哈希法,在众多请求的情况下,它确保来自同一个IP的请求会分发到相同的后端服务器。

  3. 如果handlers(处理模块)没有产生错误,filters(过滤模块)将被调用。多个filters(过滤模块)能映射到每个位置,所以(比如)每个请求都可以被压缩成块。它们的执行顺序在编译时决定。filters(过滤模块)是经典的“接力链表(CHAIN OF RESPONSIBILITY)”模型:一个filters(过滤模块)被调用,完成其工作,然后调用下一个filters(过滤模块),直到最后一个filters(过滤模块)。过滤模块链的特别之处在于:

    每个filters(过滤模块)不会等上一个filters(过滤模块)全部完成;

    它能把前一个过滤模块的输出作为其处理内容;有点像Unix中的流水线。

    过滤模块能以buffer(缓冲区)为单位进行操作,这些buffer一般都是一页(4K)大小,当然你也可以在nginx.conf文件中进行配置。这意味着,比如,模块可以压缩来自后端服务器的响应,然后像流一样的到达客户端,直到整个响应发送完成。

    总之,过滤模块链以流水线的方式高效率地向客户端发送响应信息。

  4. 所以总结下上面的内容,一个典型的HTTP处理周期是这样的:

    客户端发送HTTP请求 –>

    Nginx基于配置文件中的位置选择一个合适的处理模块 ->

    (如果有)负载均衡模块选择一台后端服务器 –>

    处理模块进行处理并把输出缓冲放到第一个过滤模块上 –>

    第一个过滤模块处理后输出给第二个过滤模块 –>

    然后第二个过滤模块又到第三个 –>

    依此类推 –> 最后把响应发给客户端。

    下图展示了nginx模块处理流程:


    点击查看大图

2 Nginx请求处理

Nginx在启动时会以daemon形式在后台运行,采用多进程+异步非阻塞IO事件模型来处理各种连接请求。多进程模型包括一个master进程,多个worker进程,一般worker进程个数是根据服务器CPU核数来决定的master进程负责管理Nginx本身和其他worker进程。如下图:

从上图中可以很明显地看到,4个worker进程的父进程都是master进程,表明worker进程都是从父进程fork出来的,并且父进程的ppid为1,表示其为daemon进程。

需要说明的是,在nginx多进程中,每个worker都是平等的,因此每个进程处理外部请求的机会权重都是一致的。

所有实际上的业务处理逻辑都在worker进程。worker进程中有一个ngx_worker_process_cycle()函数,执行无限循环,不断处理收到的来自客户端的请求,并进行处理,直到整个Nginx服务被停止。

worker 进程中,ngx_worker_process_cycle()函数就是这个无限循环的处理函数。在这个函数中,一个请求的简单处理流程如下:

  1. 操作系统提供的机制(例如 epoll, kqueue 等)产生相关的事件。
  2. 接收和处理这些事件,如是接收到数据,则产生更高层的 request 对象。
  3. 处理 request 的 header 和 body。
  4. 产生响应,并发送回客户端。
  5. 完成 request 的处理。
  6. 重新初始化定时器及其他事件。

2.1 多进程处理模型

下面来介绍一个请求进来,多进程模型的处理方式:

首先,master进程一开始就会根据我们的配置,来建立需要listen的网络socket fd,然后fork出多个worker进程。

其次,根据进程的特性,新建立的worker进程,也会和master进程一样,具有相同的设置。因此,其也会去监听相同ip端口的套接字socket fd

然后,这个时候有多个worker进程都在监听同样设置的socket fd,意味着当有一个请求进来的时候,所有的worker都会感知到。这样就会产生所谓的“惊群现象”。为了保证只会有一个进程成功注册到listenfd的读事件,nginx中实现了一个“accept_mutex”类似互斥锁,只有获取到这个锁的进程,才可以去注册读事件。其他进程全部accept 失败。

最后,监听成功的worker进程,读取请求,解析处理,响应数据返回给客户端,断开连接,结束。因此,一个request请求,只需要worker进程就可以完成。

进程模型的处理方式带来的一些好处就是:进程之间是独立的,也就是一个worker进程出现异常退出,其他worker进程是不会受到影响的;此外,独立进程也会避免一些不需要的锁操作,这样子会提高处理效率,并且开发调试也更容易。

如前文所述,多进程模型+异步非阻塞模型才是胜出的方案。单纯的多进程模型会导致连接并发数量的降低,而采用异步非阻塞IO模型很好的解决了这个问题;并且还因此避免的多线程的上下文切换导致的性能损失。

worker进程会竞争监听客户端的连接请求:这种方式可能会带来一个问题,就是可能所有的请求都被一个worker进程给竞争获取了,导致其他进程都比较空闲,而某一个进程会处于忙碌的状态,这种状态可能还会导致无法及时响应连接而丢弃discard掉本有能力处理的请求。这种不公平的现象,是需要避免的,尤其是在高可靠web服务器环境下。

针对这种现象,Nginx采用了一个是否打开accept_mutex选项的值,ngx_accept_disabled标识控制一个worker进程是否需要去竞争获取accept_mutex选项,进而获取accept事件

ngx_accept_disabled值,nginx单进程的所有连接总数的八分之一,减去剩下的空闲连接数量,得到的这个ngx_accept_disabled。

当ngx_accept_disabled大于0时,不会去尝试获取accept_mutex锁,并且将ngx_accept_disabled减 1,于是,每次执行到此处时,都会去减1,直到小于0。不去获取accept_mutex锁,就是等于让出获取连接的机会,很显然可以看出,当空闲连接越少时,ngx_accept_disable越大,于是让出的机会就越多,这样其它进程获取锁的机会也就越大。不去accept,自己的连接就控制下来了,其它进程的连接池就会得到利用,这样,nginx就控制了多进程间连接的平衡了。

2.2 一个简单的HTTP请求

从 Nginx 的内部来看,一个 HTTP Request 的处理过程涉及到以下几个阶段:

初始化 HTTP Request(读取来自客户端的数据,生成 HTTP Request 对象,该对象含有该请求所有的信息)。

处理请求头。

处理请求体。

如果有的话,调用与此请求(URL 或者 Location)关联的 handler。

依次调用各 phase handler 进行处理。

以上步骤,如下图所示:

输入图片说明

在这里,我们需要了解一下 phase handler 这个概念。phase 字面的意思,就是阶段。所以 phase handlers 也就好理解了,就是包含若干个处理阶段的一些 handler

在每一个阶段,包含有若干个 handler,再处理到某个阶段的时候,依次调用该阶段的 handler 对 HTTP Request 进行处理。

通常情况下,一个 phase handler 对这个 request 进行处理,并产生一些输出。通常 phase handler 是与定义在配置文件中的某个 location 相关联的

一个 phase handler 通常执行以下几项任务:

获取 location 配置。

产生适当的响应。

发送 response header。

发送 response body。

当 Nginx 读取到一个 HTTP Request 的 header 的时候,Nginx 首先查找与这个请求关联的虚拟主机的配置。如果找到了这个虚拟主机的配置,那么通常情况下,这个 HTTP Request 将会经过以下几个阶段的处理(phase handlers):

NGX_HTTP_POST_READ_PHASE: 读取请求内容阶段

NGX_HTTP_SERVER_REWRITE_PHASE: Server 请求地址重写阶段

NGX_HTTP_FIND_CONFIG_PHASE: 配置查找阶段

NGX_HTTP_REWRITE_PHASE: Location请求地址重写阶段

NGX_HTTP_POST_REWRITE_PHASE: 请求地址重写提交阶段

NGX_HTTP_PREACCESS_PHASE: 访问权限检查准备阶段

NGX_HTTP_ACCESS_PHASE: 访问权限检查阶段

NGX_HTTP_POST_ACCESS_PHASE: 访问权限检查提交阶段

NGX_HTTP_TRY_FILES_PHASE: 配置项 try_files 处理阶段

NGX_HTTP_CONTENT_PHASE: 内容产生阶段

NGX_HTTP_LOG_PHASE: 日志模块处理阶段

在内容产生阶段,为了给一个 request 产生正确的响应,Nginx 必须把这个 request 交给一个合适的 content handler 去处理。 如果这个 request 对应的 location 在配置文件中被明确指定了一个 content handler,那么Nginx 就可以通过对 location 的匹配,直接找到这个对应的 handler,并把这个 request 交给这个 content handler 去处理。这样的配置指令包括像,perl,flv,proxy_pass,mp4等。

如果一个 request 对应的 location 并没有直接有配置的 content handler,那么 Nginx 依次尝试:

如果一个 location 里面有配置 random_index on,那么随机选择一个文件,发送给客户端。

如果一个 location 里面有配置 index 指令,那么发送 index 指令指明的文件,给客户端。

如果一个 location 里面有配置 autoindex on,那么就发送请求地址对应的服务端路径下的文件列表给客户端。

如果这个 request 对应的 location 上有设置 gzip_static on,那么就查找是否有对应的.gz文件存在,有的话,就发送这个给客户端(客户端支持 gzip 的情况下)。

请求的 URI 如果对应一个静态文件,static module 就发送静态文件的内容到客户端。

内容产生阶段完成以后,生成的输出会被传递到 filter 模块去进行处理。filter 模块也是与 location 相关的。所有的 fiter 模块都被组织成一条链。输出会依次穿越所有的 filter,直到有一个 filter 模块的返回值表明已经处理完成。

这里列举几个常见的 filter 模块,例如:

server-side includes。

XSLT filtering。

图像缩放之类的。

gzip 压缩。

在所有的 filter 中,有几个 filter 模块需要关注一下。按照调用的顺序依次说明如下:

copy: 将一些需要复制的 buf(文件或者内存)重新复制一份然后交给剩余的 body filter 处理。

postpone: 这个 filter 是负责 subrequest 的,也就是子请求的。

write: 写输出到客户端,实际上是写到连接对应的 socket 上。