[collect]Web应用上线之前程序员应该了解的技术细节


译文链接干货:Web应用上线之前程序员应该了解的技术细节

原文链接What technical details should a programmer of a web application consider before making the site public?


《Web 应用上线前,程序员应考虑哪些技术细节呢?》这是 StackExchange 上面的一个经典问题贴。最赞回复有 2200+ 顶,虽然大多数人可能都听过其中大部分内容,但应该会有你没有深入了解的内容。一起来看看。

问题

Web 应用上线前,程序员应考虑哪些技术细节呢? 如果 Jeff Atwood 忘记把 HttpOnly cookiessitemaps 和 cross-site request forgeries 放在同一个网站,那我会把什么重要的东西也会忘掉呢?

我以一个 Web 开发人员的角度思考这个问题,别人为网站进行美化设计并填充内容。因此,他们可能认为可用性和内容比平台更重要,程序员在这方面没多少发言权了。而你需要考虑到的是:你实现平台的稳定性、安全性和满足其它商业目的(如成本不要太高、耗时不要太长和网站排名)。

而以一位已经在相当可信的环境下,完成了几个企业内网应用程序项目的开发者角度思考,并在一个流行且权威网站上为整个糟糕的万维网打响第一枪。

另外,我希望能回答得更加具体一点,而不仅仅是一个“Web标准”这样模糊的答案。通过 HTTP 传输的 HTML、JavaScript、CSS 是必须要掌握的,特别是针对那些资深 Web 开发者。所以,超出上述范围,哪一个标准?在什么环境下,并且为什么这样?麻烦您提供一个跳转到该标准说明的链接。

最佳回复

下面列表里的大部分内容,我们大多数人都应该已经听过了。所以在这之前,你可能只有一到两个项目没有深入查看和理解透彻,或甚至没听过。

界面和用户体验

  • 应意识到浏览器实现标准不一致,并确保你的网站能在所有主流浏览器上合理运行。至少起码在最近的Gecko 引擎(Firefox)、Webkit 引擎(Safari 和一些移动端浏览器)、Chrome、支持 IE 浏览器(利用 Application Compatibility VPC Images 进行测试)和 Opera。另外,也要考虑浏览器在不同操作系统下是如何渲染网站的。
  • 要考虑到用户除了通过主流浏览器来浏览网站外,还有其它方式:手机、屏幕阅读器和搜索引擎等。 这有一些相关信息:WAI和 Section508,移动开发:MobiForge
  • Staging:如何部署更新而不影响用户。进行一次或多次测试或 staging 环境可用来实现架构的更改,确保代码或全部内容能部署在一个可控的方式而不会破坏任何东西。有一个自动化的方式部署批准改变网站。最有效地实现方法是使用版本控制系统(Git、CVS、Subversion 等)和一个自动构建机制( Ant、 NAnt 等)。
  • 不要向用户直接显示不友好的错误提示。
  • 不要以纯文本的方式显示用户的 Email 地址,否则他们将会收到该死的垃圾邮件。
  • 为用户链接添加属性 rel = “nofollow” 来避免垃圾邮件
  • 为你的网站建立深思熟虑的限制– 这也属于下面将要讲到的安全性。
  • 学会如何实现网页的渐进增强
  • POST 提交成功后,要重定向,以防止再次提交引起刷新。
  • 别忘了考虑到访问性(accessibility,即残障人士如何使用网站)。这一直是好想法并且有时这是法定要求。WAI-ARIA和 WCAG 2 都是这方面很好的资源。
  • 别让用户思考如何操作。

安全性

性能

  • 如有必要,就实现缓存。了解和正确地使用 HTTP 缓存(caching)和 HTML 5 离线缓存。
  • 优化图片 – 别使用一个 20 KB 大小的图片做为一个重复背景。
  • 学习如何用gzip / deflate 压缩内容()。
  • 合并多个样式表单或脚本文件,以减少浏览器发送请求次数,而且要利用gzip 压缩文件之间重复的部分。
  • 浏览Yahoo Exceptional Performance(雅虎优越性能)网站,里面有很多优秀的指引,其中就包括提高前端性能和它们的 YSlow 工具(需要 Fixfox、Safari、Chrome 或 Opera)。另外,Google PageSpeed (以 浏览器扩展 的方式)是另一个测试性能的工具,而且它也会优化你的图片。
  • 为较小且有关联的图片使用CSS 图片精灵 技术,如工具栏(看“把 HTTP 请求减到最低”那点建议)
  • 繁忙 Web 站点应考虑将网页的内容分开存放 在不同的域名下。特别是…
  • 静态内容(也就是图片、CSS、JavaScript 和无需通过 cookies 获取的一般内容)应放进独立且不使用 cookies 的域名上,因为所有域名和其子域名为客户端生成的 cookies 都会伴随请求发送回给自己。 一个很好的选择是使用内容分发网络(CDN),但要考虑到这种情况:CDN(包括可替代的 CDN)可能会失效,这时本地副本能代替它来进行传输。
  • 将浏览器渲染页面所需 HTTP 请求数量最少化。
  • 用Google的Closure Compiler 压缩 JavaScript,当然也可以使用 其他压缩工具
  • 确保有一个ico 文件在网站的根目录,也就是说 /favicon.ico。浏览器会自动请求它,即使在 HTML 中并未提及到它。如果没有 /favicon.ico,那么请求返回的结果是 大量的 404 错误,这将会耗尽服务器的带宽。

SEO(搜索引擎优化)

  • 使用“对搜索引擎友好”的链接,比如说com/pages/45-article-title 优于example.com/index.php?page=45。是 googlebot(Google 的 web 爬虫)用来替换 #! 的。换句话说,./#!page=1 会被Google搜索引擎转成 ./?_escaped_fragments_=page=1。 (通常来说 URL 中的 # 后的东西都不会被传到服务器上,所以,为了要让 Google 可以抓取 AJAX 的东西,你需要使用 #!,而 Google 会把“#!”转成“_escaped_fragment_”来向服务器发请求,Twitter 的大量链接者是#!的,比如:https://twitter.com/#!/your_activity —— 陈皓注)。另外,用户也许会使用 Firefox 或 Chromium,那么 history.pushState({“foo”:”bar”}, “About”, “./?page=1”); 是一个很不错的命令。因为即使地址栏上的地址改变了,页面也不会重新加载。这可让你使用 ? 而不是 #!来动态加载内容了,也告诉服务器,当下次访问该页面时给该链接发邮件,AJAX 无须再发送一个额外的请求了。
  • 别使用“点击这里” 这类的链接。这是浪费一个 SEO 的机会,并且会对使用屏幕朗读器用户造成困惑。
  • 拥有一个XML 网站地图,它的默认路径最好是 /sitemap.xml。
  • 当你有多个 URL 指向同一个内容时,请使用<link rel=”canonical” … />。这个问题可利用 Google Webmaster Tools 解决。
  • 使用Google Webmaster Tools 和 Bing Webmaster Tools
  • 在一开始就正确安装Google Analytics (或一个开源的分析工具,如 Piwik)。
  • 要知道txt 和搜索引擎爬虫是如何工作的。
  • 重定向请求(使用 301 永久性移走),要求example.com 重定向到example.com (或反过来),从而防止分裂两个站点之间的谷歌排名。
  • 知道并不是所有的爬虫都是好的,有些爬虫的行为并不好。
  • 如果有非文本内容(如视频等)需要添加到Google 网站地图的话,你可以到 Tim Farley’s answer 看看,里面有一些关于这方面的,而且不错的信息。

技术

  • 搞懂 HTTP 协议,以及诸如 GET 、POST、sessions 和 cookies 这些概念,而且要知道“无状态”是什么意思。
  • 根据W3C 文档 编写你的 XHTML / HTML 和 CSS 代码,并确保它们 有效。这里的目的是避免浏览器的怪异模式,并让它们更容易在非传统浏览器(如屏幕阅读器和移动设备)上运行。
  • 搞懂浏览器是如何处理JavaScript。
  • 搞懂页面上的JavaScript、样式表单和其他资源是如何加载和运行的,并考虑它们对性能的影响。现在广泛认同的做法是:除了通用脚本,如 analytics apps 或 HTML5 shims,将其它脚本放到页面底部
  • 搞懂 JavaScript 沙箱如何工作,特别是你打算用 iframes。
  • 要意识到 JavaScript 可能会被禁用,因此AJAX 也只是一个扩展,不一定会被运行。即使大多数普通的用户并不会理会 JavaScript 被禁用,但要记住 NoScript 正变得更流行,移动设备可能默认禁止 JavaScript,而且 Google 在索引你的网站时,并不会执行大多数 JavaScript。
  • 学会区分301 和 302 重定向 的不同之处(这也是一个 SEO 问题)。
  • 尽可能多地学习你部署平台的相关知识。
  • 考虑使用Reset Style Sheet(重置样式表单) 或 css
  • 考虑使用JavaScript 框架(如 jQueryMooToolsPrototypeDojo 或 YUI 3),它们会解决很多在使用 JavaScript 操作 DOM 时的浏览器差异问题。
  • 把性能和 JS 框架合在一起讨论,考虑使用诸如Google Libraries API 服务来加载框架, 以至于浏览器能使用已缓存框架的副本,而不是从你的网站下载同样的副本。
  • 不要重复造轮子。在做任何事之前,可搜索一个组件或案例是如何实现的。但有 99% 机会是其它人已经做过了,并发布了OSS 版本的代码。
  • 另外,即时确定你需要的是什么,但也别使用太多库。特别是在Web 客户端,保持轻量、快速和灵活非常重要。

BUG 修复

  • 要明白你将花费 20% 时间敲代码,而剩下 80% 的时间是在维护你的代码,所以代码质量很重要。
  • 建立一个良好的错误报告解决方案。
  • 为用户提供一个能向你提交建议与批评的系统。
  • 为将来的维护和技术支持人员撰写文档,解释清楚系统是怎么运行的。
  • 经常备份!(并确保那些备份是可用的)除了备份机制,你还必须有一个恢复机制。
  • 使用版本控制系统来存储你的文件,如SubversionMercurial 或 Git
  • 别忘记进行验收测试。框架(如Selenium)能为你提供相应帮助。特别是如果你想完全自动化测试,也可通过使用持续集成工具,比如 Jenkins
  • 在网站运行时,要确保你有足够的日志,当然你可以使用框架,如log4jlog4net 或 log4r。因为当你的网站某部分发生错误,你将需要一种方式找出是哪里发生的。
  • 当日志能确保你能同时捕捉到处理异常和未处理异常。那么可通过记录/分析输出的日志,可显示网站的关键问题出现在哪里。

其他

  • 服务器端和客户端都要监控和分析(应主动而不是被动)。
  • 使用能与用户保持联系的服务(如UserVoice 和 Intercom,或其它类似的工具)。
  • 采用Vincent Driessen 的 Git 分支模型(Git branching model)。

文中有很多省略掉的东西,并不是因为它们不是有用的答案,而是它们过于详细,且超出本问题的范围。而对于想懂得更多的人来说,他们希望学到更多的东西,因此他们应该知道这些概述。另外,我也欢迎大家编辑补充这个答案,因为我可能忽略了一些东西或犯了一些错误。


说明:译文的转载征得了译者的同意,在此感谢译者J.c,同时也非常感谢StackExchange的各位奉献了经典的问答!

==

更多参考链接:

《“[collect]Web应用上线之前程序员应该了解的技术细节”》 有 26 条评论

  1. cookie安全的注意点
    `
    不可伪造:cookie的设计要有不可猜测性
    Httponly:防止cookie被xss偷
    https:防止cookie在网络中被偷
    Secure:阻止cookie在非https下传输,很多全站https时会漏掉
    Path :区分cookie的标识,安全上作用不大,和浏览器同源冲突
    不区分端口 :同主机不同端口的cookie会被共享
    `
    http://lvwei.me/passport.html

  2. 如何提升页面渲染效率
    http://icodeit.org/2017/02/frontend-page-performance-tuning/
    `
    像素渲染流水线

    下载HTML文档
    解析HTML文档,生成DOM
    下载文档中引用的CSS、JS
    解析CSS样式表,生成CSSOM
    将JS代码交给JS引擎执行
    合并DOM和CSSOM,生成Render Tree
    根据Render Tree进行布局layout(为每个元素计算尺寸和位置信息)
    绘制(Paint)每个层中的元素(绘制每个瓦片,瓦片这个词与GIS中的瓦片含义相同)
    执行图层合并(Composite Layers)
    `

  3. 谈谈网站架构设计开发的一些来龙去脉
    https://acejoy.com/2017/12/19/%E8%B0%88%E8%B0%88%E7%BD%91%E7%AB%99%E6%9E%B6%E6%9E%84%E8%AE%BE%E8%AE%A1%E5%BC%80%E5%8F%91%E7%9A%84%E4%B8%80%E4%BA%9B%E6%9D%A5%E9%BE%99%E5%8E%BB%E8%84%89/
    `
    1、初始阶段的网站架构
    2、应用服务和数据服务分离
    3、网站使用缓存
    4、应用服务器集群部署
    5、数据库读写分离
    6、网站使用反向代理和CDN加速访问
    7、使用分布式文件和分布式数据库系统
    8、使用NoSQL系统和搜索引擎
    9、应用拆分
    10、分布式服务
    `

  4. 网站优化实战
    http://jartto.wang/2019/02/16/web-optimization/
    `
    网站优化是前端开发的重中之重,但是优化细节却十分繁杂。没有好的思路,优化很难高效的开展。本文将以实际网站来做参考,手把手教你如何一步步做好网站优化。

    这不是一篇 基础网站优化 文章,继续下文前,请确定已经做了如下基本优化:
    1.图片压缩、合并
    2.代码精简、混淆
    3.减少 iframe 使用
    4.避免图片 src 为空
    5.减少 HTTP 请求数
    6.避免重定向
    7.样式表放页头,脚本放底部

    我们从头优化下来,做了不少代码改动,也达到了不错的效果。但是有几点还是需要注意:
    1.尽可能减少白屏出现时间
    骨架图解决 webview 加载页面过长的白屏过程。

    2.关注整站性能,如 TTFB
    服务端接口也需要同步优化,而不要仅仅依赖前端单方面优化。

    3.按照使用情况加载优先使用的资源
    css 预加载
    font 预加载
    js 预加载
    图片懒加载

    4.请高效利用 DNS 和 CDN
    增加缓存时间
    DNS 预解析

    网站优化从来不是一蹴而就,需要不断的去优化细节,不断的摸索尝试。从我的角度来看,其实优化更像是在网站性能和加载速度之间找到一个平衡点。譬如,文中我们为了优化文件打包大小,进行了大文件拆分。随之而来的问题就是拆分后的文件可能还会对某些文件有依赖,那么就影响到了关键渲染路径。

    所以,优化不存在什么奇技淫巧,不断的去尝试,找到这个最佳优化点,这才是根本。
    `

  5. 在浏览器输入 URL 回车之后发生了什么(超详细版)
    https://4ark.me/post/b6c7c0a2.html
    `
    前言
    注意:本文的步骤是建立在,请求的是一个简单的 HTTP 请求,没有 HTTPS、HTTP2、最简单的 DNS、没有代理、并且服务器没有任何问题的基础上,尽管这是不切实际的。

    大致流程
    一、URL 解析
    二、DNS 查询
    三、TCP 连接
    1. 应用层:发送 HTTP 请求
    2. 传输层:TCP 传输报文
    3. 网络层:IP协议查询Mac地址
    4. 链路层:以太网协议

    四、服务器处理请求
    五、浏览器接受响应
    六、渲染页面
    1.HTML 解析
    2. CSS 解析
    3. 渲染树
    4. 布局与绘制
    5. 合并渲染层
    6. 回流与重绘
    7. JavaScript 编译执行
    1. 词法分析
    2. 预编译
    3. 执行

    参考文档
    `

  6. [译] 密码哈希的方法:PBKDF2,Scrypt,Bcrypt 和 ARGON2
    https://zhuanlan.zhihu.com/p/113971205
    https://github.com/xitu/gold-miner/blob/master/TODO1/password-hashing-pbkdf2-scrypt-bcrypt-and-argon2.md
    `
    关于如何安全的存储密码以及使用何种算法总是有很多的争论:MD5、SHA1,SHA256、PBKDF2,Bcrypt、Scrypt、Argon2、明文??

    因此,我试图分析并总结了最新的合理选择:Scrypt、Bcrypt 和 Argon2 是符合条件的,MD5、SHA1、SHA256 就不太适合存储密码!

    为什么会有用于密码哈希的慢方法?概括的说:

    * 攻击者通常拥有与我们不同的、更专业(强大)的硬件
    * 攻击者之所以使用专业的硬件,是因为它能根据某些算法进行定制,定制化的硬件允许某些算法能比非专业硬件(CPU)上运行的更快,而且 —— 总体而言 —— 某些算法还可以并行化;
    * 我们依赖慢哈希方法来对密码进行哈希,从而实现你采用的 CPU/GPU 处理器与攻击者的 GPU/FPGA/ASIC 处理器在计算能力上处于同一水准。

    那么今天什么是安全的呢?
    原理还是一样的:我们需要一个加密社区审核过的慢函数并且依然未被破解。

    PBKDF2 已经存在很长时间了,像之前文章讨论的一样,它有点过时了:轻松的在多核系统(GPU)上实现并行,这对于定制系统(FPGA/ASIC)来说微不足道。所以我拒绝了它。

    BCrypt 在 1999年 就产生了,并且在对抗 GPU/ASIC 方面要优于 PBKDF2,但是我还是不建议你在新系统中使用它,因为它在离线破解的威胁模型分析中表现并不突出。

    SCrypt 在如今是一个更好的选择:比 BCrypt设计得更好(尤其是关于内存方面)并且已经在该领域工作了 10 年。

    Argon2 在 2015 年 7 月赢得了密码哈希竞赛。Argon2 有两个主要的版本:Argon2i 是对抗侧信道攻击的最安全选择,而 Argon2d 是抵抗 GPU 破解攻击的最安全选择。

    Argon2d 使用依赖数据的内存访问,这使得它很适合用于加密数字货币和工作量证明的应用程序,而不会受到侧信道定时攻击的威胁。Argon2i 使用与数据无关的内存访问,这是密码哈希的首选方法。Argon2id 在内存第一次迭代的前半部分充当 Argon2i,其余部分则充当 Argon2d。因此,基于时间 —— 空间的平衡,它既提供了侧信道攻击保护也节约了暴力开销。Argon2i 对内存进行了更多的传递,以防止权衡攻击的发生。

    如果你担心侧信道攻击(例如:恶意数据缓存加载/幽灵漏洞,它允许通过基于缓存的侧信道读取同一硬件上其他正在运行的进程的私有内存数据),你应该使用 Argon2i,否则使用 Argon2d。 如果你不确定或你对混合方法感到满意,你可以使用 Argon2id 来获得两个方面的优势。

    在 2019 年,我建议你以后不要使用 PBKDF2 或 BCrypt,并强烈建议将 Argon2(最好是 Argon2id)用于最新系统。
    `

  7. Password Hashing: PBKDF2, Scrypt, Bcrypt
    https://medium.com/@mpreziuso/password-hashing-pbkdf2-scrypt-bcrypt-1ef4bb9c19b3

    Password Hashing: Scrypt, Bcrypt and ARGON2
    https://medium.com/analytics-vidhya/password-hashing-pbkdf2-scrypt-bcrypt-and-argon2-e25aaf41598e

    What is the specific reason to prefer bcrypt or PBKDF2 over SHA256-crypt in password hashes?
    https://security.stackexchange.com/questions/133239/what-is-the-specific-reason-to-prefer-bcrypt-or-pbkdf2-over-sha256-crypt-in-pass

    Do any security experts recommend bcrypt for password storage?
    https://security.stackexchange.com/questions/4781/do-any-security-experts-recommend-bcrypt-for-password-storage/6415#6415

    Question: Is there any reason to prefer bcrypt over pbkdf2, or vice versa?
    https://news.ycombinator.com/item?id=7286057

  8. Making a Website Under 1kB
    https://bt.ht/1kb/
    `
    I recently launched (another) website club called the 1kB Club. Unlike the 1MB Club, it isn’t as accessible for most modern websites to become official members. Building a website that actually serves useful content while squeezing its page size under 1,024 bytes is no easy feat.

    But it is possible. And I did it myself!

    ==
    Next, you might have caught the odd favicon meta tag:

    This is required to stop the browser from making the standard favicon request (normally pulling from favicon.ico). **By adding this meta tag you are telling the browser to load in an empty image without running another server request.** This saves about 400 bytes of bandwidth on its own!
    在页面中添加上面的这行meta标签,告诉浏览器加载一个空图片,而不是单独发起一个服务端请求,就可以每次减少 400 字节的带宽。

    ==
    如何关闭 favicon 请求(英文)

    作者想制作一个体积尽量小的网页,文章里面介绍了一个技巧,如何让浏览器不发出 favicon 请求。
    `

回复 a-z 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注