上次我写《前端工程师必知必会》已经是三年前了,那是我写过最火的文章了。三年了,我仍然会在Twitter上收到关于这篇文章的消息。

从2012年到现在,一篇文章都没发过让我觉得有点羞羞哒。三年是一段很长的时间,很多东西都发生了改变。2012年,我鼓励同学们去学习浏览器开发者工具和模块化;虽然有很多同学会觉得CSS预编译和客户端模板引擎并不靠谱,但我仍然想要说一说它们;还有JSHint,虽然有#getoffmylawn(滚出我的地盘)的警告,但依然无法阻止JSHint成为一个受欢迎的理念(准确的说,JSLint真的(只是)存在过)。

已经是2015年了,我想写一篇新的,但是当我坐下来开始动笔的时候,想到了两个事情。一,这些东西被称作“必知必会”可能有人会觉得不太公平——如果你已经觉得2012年的那篇文章如此,那本文也是一样的了。也许有同学会说,我们应该把 “足够应付业务需求的技能” 作为 “前端必须掌握的知识”,但考虑到前端行业里也有各种各样的工作可供选择,这么做也只能得到一个并不适合所有人的 “前端基础知识”。对于我来说,我需要的不是工作,我想要的是被邀请去做一份牛逼的工作。我想要的不只是去干活而已,而是想和一群牛逼的人一起做牛逼的事。我不想仅仅满足于用已有的知识来完成现在的工作,而是希望掌握更多的知识来解决未来将会面对的问题。

第二,我现在已经完全把Javascript作为我的核心了:CSS知识只有在必须关注性能问题时才会用到,其他场景已经用的越来越少。我知道有很多牛逼的前端同学并不是这样的,但我也意识到,关注JS的同学和关注CSS的同学之间的距离也越来越远。这可能需要在另起一篇文章来讨论,不过我想说的是,这篇文章中不会有介绍CSS技能标准的内容,因为我还远远没有达到能那么做的水平。

总之,就算这个技能列表并不适合你的前端工作,没关系,不要有压力,地球也不会爆炸。

Javascript

回想2009年,那时候当你知道 HTML5 在2014年才能用的时候,你是不是觉得这辈子基本上都用不到它了?如果是,那么你需要准备好接受进展缓慢但是已经趋于稳定的ES6了,它也是下一代的Javascript(现在叫 ES2015 了,嗯,这名字至少表示今年就能用了)。就我而言,ES6,额,ES2015 无疑是我个人现在最关注的 Javascript 内容。在 ES6 中将会出现一些比较大的变化:类,真正的私有,经过改进更易用的函数和参数设定,可导入的模块,等等等等。那些掌握和理解新的语法的同学以后将会在 JS 社区牛逼闪闪。相关阅读:

  • Understanding ES6,Nicholas Zakas 正在写的书。
  • BabelJS,一个可以把你写的 ES6 的代码编译成 ES5 并在现代浏览器中运行的工具。他们也有一个不错的介绍 ES6 的文档
  • ES6 Rocks,里面有大量的文章探索 ES6 的特性,语义和缺陷。

你也许会问:那我需要成为一个 ES6 专家么?也许现在不需要,但至少你得和你的同事懂的一样多吧?或者比他们稍微多一点?当然,如果能在你的下一个新项目中作为一个娱乐性的技术尝试也是不错的,做好准备肯定没错的,因为我们永远不知道下一刻会发生什么。

先不说新的语言特性,使用回调和 promises 管理异步 Javascript 至少得背的滚瓜烂熟吧。浏览器端应用加载,以及应用间通信策略得形成一套自己的观点吧。而且你应该知道哪种框架最适合你,而不是现在还把时间花在理解各种框架的实现原理和该选择哪种框架上。

模块化和构建工具

毫无疑问,模块化是构建 Web 客户端应用的基石。回到2012年,关于使用哪种模块化(AMD/CommonJS)方案构建浏览器端应用还存在很多争论。而最近慢慢火起来的UMD则在保证代码可复用的前提下尝试避免这样的问题。 其实也没什么好争得,毕竟这俩玩意儿之间也就差几个字符吧?

我觉得类似这样的争论其实并不都需要有一个答案,这也是我觉得从2012年到现在我们发生的最大的转变,当然,也许只是我自己这么认为。因为我觉得与其说“我再也不用 AMD 了”之类的话,倒不如多去讨论 “在开发和打包过程中使用 CommonJS 和 npm 遇到的各种难题” 来的更有价值。

虽然很感激RequireJS曾经对模块化做出的贡献,不过现在我开始有点迷恋webpack了。 webpack 的构建配置比 RequireJS 更加易于理解,也更具访问性。通过它的热插拔特性和内置的本地静态服务器可以让发布更加便捷。它并不强制要求使用 AMD 或者 CommonJS – 两个它都支持。它还实现了一大堆加载器,用来完成常见的繁琐工作。Browserify也值得去了解一下,不过我个人认为它比 Webpack 落后很多。一些靠谱的朋友告诉我说systemjs也是这个领域的竞争者,不过我还没有用过,而且它的文档烂的我连看都不想看。不过我觉得它的好基友jspm(包管理器)比较有趣,jspm 可以让你从各种包管理服务器加载你需要的各种组件,(组件必须是符合 ES6, AMD, CommonJS and globals 规范的),包括 npm, github 等,但是我对于这两个玩意的合体还是有点不太理解。啊,还有,虽然我说了这么多关于模块化之外的内容,但我从来没想过放弃 AMD,我们边走边看吧。

我觉得如果要停止对模块化和构建工具的争论,形成统一的模块化系统,并且在这个系统里面,任何项目的代码都可以共享,而且还不需要 UMD 这样额外的补丁工具,我们还有很长的路要走。理想状况下,ES6 modules的到来会解决这些问题,不过在这一天到来之前,类似 UMD 之类的转换器会填补这些空缺,不过貌似这样做我们又把事情变得复杂了,好像我们也总喜欢把事情弄得复杂。

与此同时,前端开发人员也需要对构建工具,各种模块化系统有自己的见解和知识储备。不管是好是坏,根据 Javascript 现在的进度,你的模块化策略会对你的项目有比较大的影响。

测试

客户端的代码测试变得越来越普遍,最近也诞生了一些新的测试框架:KarmaIntern。我发现基于 promise 的 Intern 的异步测试方法相当优雅。不过可能是因为习惯,我大多数情况下还是用 Mocha 写测试用例。

测试的主要障碍其实是前端开发者的代码编写方式。我在2012年发表过一个关于《编写可测试的Javascript》下载地址的演讲,紧接着几个月后又发表了一篇相关的文章

测试的第二大障碍是工具。Webdriver 是一个艰难而巨大的工作。目前在各个浏览器端做持续集成的 UI 自动化测试基本上是不可能的,更不用说移动端了。我们仍然停留在局限于某一小部分浏览器和设备上做轻量级的自动化功能测试,尽我们所能去研究怎样快速,低成本的进行这种测试的阶段。

如果你对如何改进代码的可测试性感兴趣的话,那么唯一一本最值得看的书是Working Effectively with Legacy Code中译版:《修改代码的艺术》。作者 Michael Feathers 定义了“遗留代码”的概念:任何未经测试的代码都是遗留代码。在测试领域,最基本的要素就是上面这句话,尽管你可能不这么认为。

流程自动化

你首先会想到Grunt,这也是理所当然的。而GulpBroccoli的自动化构建方式也别具匠心。我没用过Broccoli,只玩过Gulp,我也开始意识到Grunt对于依赖其他服务的复杂任务的自动化工作存在局限性,尤其是当这种任务每天需要运行上千次的时候。

Yeoman是在我写完2012年的那篇文章仅仅45天之后发布的,我承认当时我并没有及时去尝试一下。不过最近我开始启动一些新项目,这些新项目有两个特点
a) 这些项目都是从零开始
b) 尝试用一些不同的技术方案,试图通过这种方式找到 Bazaarvoice(提供第三方点评服务)上第三方 JS 应用的规范化的开发方式。
Yeoman 在这两方面做的都很好。一个简单的 yo react-webpack 命令就可以为你初始化好你的项目,然后各种你想要的玩具也都应有尽有:生成测试用例,本地静态服务器,hello world 入门程序,等等等等。如果 React 和 webpack 不是你想要的,也许你会在 Yeoman 的 generators(项目生成器)里面找到一个你想要的,当然,自己自定义一个这样的构建包也是比较容易的。

鉴于 Yeoman 只是一个在项目开始时才会用到的构建工具,并且鉴于我们并不是总是做新项目,所以大多情况下了解一下就够了。除非,你也想去规范整个项目开发过程,那么它可能会更有价值一点。

Broccoli 已经得到了 ember-cli 的采纳,我觉得他们的配对可能会有一个新名字,这样在未来才比较方便和 Grunt /Yeoman 对抗。而 Grunt 和 Yeoman 的开发进度也放缓了,所以未来会发生什么,我们还是静观其变吧。

代码质量

如果你像我一样,一看见违反代码规范的代码时就开始抓狂,那么JSCS
ESLint就是老天赐给你的礼物,而2012压根就没这些玩意。他们都提供了自定义代码规范的方式,并且可以在代码提交前对你的代码做自动化校验。这让我想起了…

Git

从2012年到现在,github 的使用流程并没有发生很大的变化,比如在 pull request 页面连个分支名都没有(只是恶搞一下)。

你应该非常清楚和流畅地使用功能分支(feature branches), 使用 rebase 合并别人的代码干活,使用交互式 rebase 命令和 squash 合并提交记录,或者尽可能细颗粒度的划分项目内容,避免引起代码冲突。另一个可用的 Git 工具是钩子,具体而言,就是你可以在 push 前,commit 前,执行你的各种测试用例,检查代码质量。你可以自己写钩子,也可以使用ghooks,由于 ghooks 使钩子工作变得非常简单,所以你简直没有理由不用它。

客户端模板

这可能是我在2012年的那篇文章中写的最烂的内容了,某种意义上的“烂”。客户端模板还是很有价值的,而且它已经被内置到 ES2015 里面了,这不仅仅只是一件好事而已。这些年也有一些惨重的教训,不少团队把所有的渲染工作全部丢到浏览器端去做,结果产生了严重的性能问题,所以 “在浏览器端渲染生成所有 HTML” 的做法理所当然的被摒弃了。 而更为聪明的做法则是,把 HTML 生成放在服务器端,或者通过预编译的方式,先将模板做为静态资源储存起来,在需要时快速的编译成 HTML,需要更新时也可以直接在客户端更新模板。

这里会有一些新的展望,不仅是对我自己,也是对所有人,当你在考虑性能问题时,也许没必要把自己完全限定在浏览器范围内。所以,这又让我想起了……

Node

听说你懂 Javascript,那么我觉得你也应该懂 Node,至少在遇到 Node 问题是能帮得上忙的,如果连忙都帮不上,那也至少深入研究一下吧:Node 的文件系统,流,服务器,完全不同于前端的一些开发模式等等。对后端敬而远之只会限制我们前端的发展潜力。

即使你的真实生产环境中后端不用 Node,当你的工作被后端限制或阻碍的时候,Node 也是一个非常有用的工具。最起码,你也应该熟悉怎么去初始化一个 Node 项目,怎么用 Express 搭建服务器设置路由,怎么使用请求模块代理请求。

最后

感谢 Paul, Alex, Adam, Ralph 对本文的 Review,感谢他们毫不吝啬的指出我的不足之处,并给我提了很好的意见。

就这样,祝你好运。也许,三年之后我们会再见。

原文链接: A Baseline for Front-End ‘JS’ Developers: 2015