一.前言

很多情况下,产品的设计与开发人员一直想打造一套高品质的解决方案,从而快速、平稳地适应产品迭代。速度是衡量产品适应性的真正且唯一的标准,而且,这并不是笔者的一家之言。

「速度是衡量适应能力的真正指标。」 ——艾瑞克·埃利奥特

许多公司选择 JavaScript,就是看中了它灵活、快速的优点。尽管此言非虚,但如果你在构建 JavaScript 系统时考虑得不够周全,灵活与高速的特性反而可能将你带入歧途。

一些值得特别关注的问题包括:

  • 代码重复
  • 样式或风格不一致
  • 无法随意扩展
  • 工具与模块选择阻碍了生产力
  • 测试程序不可靠或缺失
  • 深度继承(猩猩/香蕉问题)

原作者曾在多个侧重 JavaScript 的开发环境中工作了一段时间之后,几乎经历了所有扩展 JavaScript 应用可能导致的问题,客户端与服务器端均不能幸免。以下是对这些问题的总结,希望能帮助大家少走一些弯路。

JavaScript 踩坑心得— 为了高速(上) 技术分享

二.基础性原则

在探讨与上下文相关的 JavaScript 问题之前,以下是一些与平台相独立的建议,肯定能帮助你减轻工作负担。

1.避免经典的面向对象模式

JavaScript 功能非常强大,它为对象组合提供了原型继承与函数式编程功能,使用 JavaScript 的这两大支柱功能,而不执着于经典的面向对象模式,能够有效发挥 JavaScript 的强劲功能。应用的组合度与模块化程度越高,今后就越容易重构与扩展。

2.越懒越好

现而今,NPM 上提供了超过20万个模块。时间就是金钱,你花在代码维护上的时间越多,对雇主而言,你就越昂贵。更何况,许多代码其实不用你亲自编写。

在这里,笔者还建议你使用第三方的运维服务与工具。没必要建立自己的分析平台,除非你的应用扩展到非常大的规模,以致于 Google Analytics,Mixpanel,百度统计等 SaaS 营销软件无法满足你的需求。使用这些服务处理相关任务,能促使你专注于真正重要的东西——产品,而且,现在研发的人力成本越来越高,使用适当的 APM 软件也能减少开发维护网站的任务量,例如 OneAPMNewRelicAPPdynamic 等,这能让工程师专注于生产价值,而不是管理代码质量。

3.保持一致性

导致生产力严重下滑的另一重要原因是面对陌生代码时手足无措,四处翻找。采用统一的风格指南,创建可辨明的样式,就能解决这一难题。同样的风格与样式意味着新的项目看起来也更为熟悉。

笔者尤其偏爱 Airbnb 的风格指南。该指南的贡献者超过 160 人,每个月有16.9万次的下载。此外,它还提供了一个 ESLint 插件,也就是说,如果你不准备覆盖什么的话,无需任何配置就能为你所用。

与成千上万名 JavaScript 工程师共享样式与风格。

此外,使用 linter 以确保团队内部的样式一致。目前,ESLint 是笔者最爱的 linter,因为它不仅提供了插件能力,还拥有来自开源社区的持续支持。几乎针对每一种文本编辑器与 IDE,都有 ESLint 插件可用。

Yeoman 也可以帮你创建在新项目中使用的应用模板,实现更为深入的一致性。有了 Yeoman,你可以在每个应用中使用相同的基本依赖关系,编码样式以及风格。

4.充分利用丰富的工具

JavaScript 是拥有最完备的工具生态系统的编程语言之一。请一定要利用这一点!iron-node,react devtools 和 redux devtools 都是不容错过的工具。

Electron 与 React Native 提供了访问原始环境的能力,允许你为对种平台创建应用,而且,能有效提高代码重用率。

三.编写过程中的「坑」
1.尽可能保持小巧

将应用分为许多小巧的模块,能真正实现可组合的 JavaScript。遵循 FIRST 原则(Focused 专注,Independent 独立,Reusable 可重用,Small 小巧,Testable 可测试),能够降低应用复杂度,同时提升测试能力与重用率。

「无论是客户端组件还是服务器端的组件,无论是 Node 模块还是一段可视化 UI,庞大的组件总是比小巧的组件更复杂,更难以维护。」 ——阿迪·奥斯马尼

请记住,模块的功能越小越好。事实上,模块越小,其重用率就越高。

2.充分利用 ES2015

将其用于 APIs,SPAs,以及两者的所有中间环节。类似 Bable的工具能给你带来极大的优势。在今天,使用 ES2015 的能力意味着你可以用更少、更整洁的代码创建应用。不要因为害怕供应商锁定或这些工具不容易找到而放弃使用它们。

老实说,现在已经没有理由不适用 Babel 了!Bable 既可以处理普通的 JavaScript,也可以处理任何类型的编译代码。这意味着,你可以随时将模块移回 ES5。

建立能与 JavaScript 完好扩展的服务并非易事。应用越大,快速运行并适应新变化就越难。请确保你正在建造的服务是高度可用,且支持自动扩展的。

3.建立支持 JavaScript 应用的基础架构

JavaScript 是一种单线程的语言。这意味着,在没有集群的情况下,你的应用只能使用单个 CPU。笔者喜欢将负载平衡工作留给代理或 NGINX 之类的负载平衡器,而不是交由 Node 的集群模块处理。此外,笔者还偏好使用较小的服务器来运行应用。这样,当需要更多资源时,笔者只需增加服务器的数量就能轻易实现横向扩展。这能帮助笔者最小化当前的运营成本。

4.集装箱化!集装箱化!集装箱化!

以下是部分原因:

  1. 集装箱化会迫使你遵从应用开发12大原则
  2. 通过集装箱化,可以实现开发、阶段、测试以及生产环境的对等。
  3. 集装箱非常易于横向扩展。
  4. 你可以轻易将应用转移到其他云服务上。(防止供应商锁定,使用其他支出服务。)

实现环境集装箱化的理由还有很多很多,一旦掌握了基本知识,集装箱化就不难实现。如果你想打造在任何平台都能使用的灵活应用,集装箱化是必须掌握的第一步。而且,由于集装箱在外部是无状态的,可以支持无限次复制。

5.打造易于扩展与维护的应用

对于 APIs 与服务,选择 Hapi 作为服务器框架,Joi 用于校验,hapi-swagger 插件用于维护活文档,是相当不错的组合。

Hapi 特别适用于模块化的大型应用,同时也能为简单的应用提供支持。此外,最让它与众不同的是其提供的封装能力。Hapi 提供了许多通过依赖注入访问服务器的「插件」。这样,你可以将业务逻辑按照紧密程度进行分组。将应用分解到这些插件中,能极大地提高扩展能力。项目的操纵也变得极为直白,原因是不需要学习自定义的插件架构,而 Hapi 本身又提供了丰富的文档资料。

Joi 是一种验证模块,与 Hapi 出自同一班工程师之手(Walmart Labs)。Joi 的 API 与其卓越的功能使得验证变成小菜一碟。你知道如何建立验证模式,因此创建验证模块也变得非常简单。用于验证 UI 中某个表格的一段代码也可以用来验证一个传入的请求、一个模块,或测试。的确是非常令人惊奇。

将 hapi-swagger 插入服务器后,你可以轻易地将任意路径标记为 API 的一部分,hapi-swagger 会帮你生成活文档。更不用说,hapi-swagger 会读取 Joi 验证,为开发者提供细致的 API 文档,而你不用费吹灰之力。不过,使用 Express 或 Koa 也可能得到相同的效果,但笔者仍旧认为 Hapi 是非常惊人的工具。

四.关于后续

本文主要讲的是关于 JavaScript 使用过程中的一些基础性的心得体验,不一定适合每一个人,但是确实也是作者的「踩坑之得」,大家在阅读之后如果有什么想分享的也可以在讨论区进行回复,闭门造车总是不行的。

本文的下一个姊妹篇,主要讲的内容预计为关于 JavaScript 使用过程中如何提高用户体验和性能优化这方面的内容,敬请期待~

Browser Insight 是一个基于真实用户的 Web 前端性能监控平台,能够帮大家定位网站性能瓶颈,网站加速效果可视化;支持浏览器、微信、App 浏览 HTML 和 HTML5 页面。想阅读更多技术文章,请访问OneAPM 官方技术博客