本文是作为一个多年不以前端为主职工作,但是时不时就是喜欢搞点前端东西的人的一个总结。我对前端的熟悉域大概是停留在 14-15 年,那时 AngularJS 还是 1.0 版本,与 React/Vue 的三足鼎立之势还没有真正展开,后面我对前端的关注就少得多了,所以,如果你觉得本文的内容和思考略微过时,很希望你能够留言或者发邮件给我进行指出,我很希望了解一下最新的一些动态,谢谢。

1. 为什么那么多大前端都使用 npm

说实话,我对 npm 的理解还停留在 node 的包管理工具的阶段,但是,正如我所看见的,无论是 node 后端项目还是大前端项目,现在很多项目都是以 npm 来作为依赖管理以及项目编译了。于是我就有兴趣观察一下为什么会发生这样的转变,然后我发现这其实是大前端急剧膨胀的情况下的一个自然选择。在 13/14 年之前,那时的前端还是比较风平浪静的,DIV + CSS 还是占有半壁江山,HTML5 和 CSS3 逐渐掀起了波澜,那时的 Angular 和 React 还处于刚刚起步的阶段,前端也还没有学不动的阶段,但是,随着 Angular 和 React 的兴起,后续 Vue 在国内市场(国外市场我发现 Vue 其实很少人用)的崛起,以及 node 的日渐强大,大前端已经发展到让人学不动的地步了。

大前端让人学不动我个人看法主要体现在两方面:

在这样的情况下,当你要构建一个项目的时候,像以前一样 cp 到 http server 的 static directory 就显得有点捉襟见肘了,而且,对于 hyper 和 Electron 场景这根本行不通,所以就需要一个 build framework,而对于大前端的兄弟姐妹们来说,Makefile 和 Yum/Apt 这一套似乎显得有点年迈和无力,于是一款比较接近于大前端习惯的 npm scripts 便成了顺手的工具。

当然,这些都是我个人的观点,欢迎留言交流讨论。

2. scss 是什么,和 css 有什么关系

这个其实可以和 1 中的观点结合起来,随着大前端的发展,无论是功能性还是定制性都得到了极大的提高,HTML5 和 css3 带来了大量的新特性,让前端的展示效果也有了极大的提高,于是乎,要想像以前一样手写 css 和 js 可能就不那么容易了,而且,因为有了一些新思想的影响,大前端的兄弟姐妹们也就想将时间花在更有价值的地方上,所以就衍生出了 scss 和 coffeescript 这样的工具,这其实让我想到了以前就有类似的事情了,HTML 繁琐的语法让 Emmet 这样的工具得到了大家的热捧。

所以到底什么是 scss 呢?从 sass 的官方首页的介绍来看,我的理解是 scss 是 sass 的其中一种实现,而 scss 完全兼容 css 的语法,也就是说一个合法的 css 文件可以被 scss 识别并解析,但是注意的是一个合法的 scss 文件未毕能够被 css 解析,因为 scss 扩展了 css 的功能,使得编写出来的 css 更加的具有可读性和可维护性,例如下面这个例子,以前我们可能需要这么写:

这里可以看到其实有一些共同的部分,在实际应用于 HTML 的时候,我们可能会关注这些关系,当使用 scss 来编写的时候,可以这么写:

这样就在可读性和一致性上得到了较好得控制。而 scss 虽然可以在浏览器编译,但是通常得操作都是在服务端/CI 编译,所以经常你会看到都是用 npm scripts 来执行的。

3. 为什么要有前端框架(Angular/React 这些)

在我常写前端的那个年代,流行的还是 PHP 这样的后端渲染 HTML,很多的页面都是后端渲染出来的,如果说有一些值得一吹的话,那可能就是 Ajax 了。那时还没有前端框架,如果要说有类似的,那么就是和 Ajax 配合默契的 JQuery 工具,JQuery 提供一套便利的操作 DOM 的工具集,通过 JQuery,可以以函数调用的方式操作 DOM,例如,我想获取一个文本框的内容:

  1. // Get the value from the selected option in a dropdown
  2. $( "select#foo option:checked" ).val();
  3. // Get the value from a dropdown select directly
  4. $( "select#foo" ).val();
  5. // Get the value from a checked checkbox
  6. $( "input[type=checkbox][name=bar]:checked" ).val();
  7. // Get the value from a set of radio buttons
  8. $( "input[type=radio][name=baz]:checked" ).val();

然后通过 Ajax 与后台交互,获取到数据之后,再以 DOM 的形式将结果反馈到 HTML 中。这些麻烦的 DOM 操作工作都是需要人工写代码来完成的,而且是很重复的,有的时候还需要仔细得调试。

而这个时代的模式是一个典型的 MVC 模型,其中前后端 Ajax 交互的是 Model,HTML 展示的是 View,而 JQuery 就是其中的 Controller。但是,这里其实有一些模糊或者说是尴尬的地方,那就是 View 中会参杂一些 Controller 的逻辑,例如 button 的 onClick,而 Controller 又有时会参杂 HTML 代码块,例如后端直接返回一个 HTML 片段,所以为了解决这个问题,框架就出现了,演变成了 MVVM 模型。

在 MVVM 模型的,将 C 转换成了 View Model 模型,整体架构是这样的:

在这个架构模型下,View(HTML)与 ViewModel 进行绑定,这样当 View 的数据变动的时候,ViewModel 可以即时响应,例如输入框输入了值,那么 ViewModel 的变量可以即时获取到,不需要我们自己写 JS 代码来作获取操作了;同样,如果 ViewModel 的变量的值变动了,对应绑定的 View 组件的值也会被更新,这样就简化了大量的开发工作。

同时,这些框架的引入不只是做了这么点事情,还有模块化组件这些工作也是非常重要的,对于前端的敏捷化提供了很大的帮助,所以总结起来,决定性的因素:

4. HyperAPP

之所以现在前端不简单地叫前端,而是叫大前端,很大一个因素的 APP 的兴起以及 HTML5 规范的发布。大家发现,以前 HTML 的前端和 APP 的前端可以是相通的,于是乎就出现了 HyperAPP,其实就是外面是一层原生 APP(用 Java/ObjectC等开发的)的套壳,然后里面可以加载 HTML5 页面,而这个 HTML5 页面还包含可以和外面一层原生壳交互的 JS,这样可以做到不重新发布 APP 也可以动态更新 APP 的内容,而且使用体验损耗并不大。

近两年 weixin 在推的小程序原理上类似,不过人家号称更进一步得做了一些优化,所以体验效果更佳。

然而,经过时间的考验,发现这条路子并不怎么行得通,原来理想化得 HyperAPP 可以开发一次,IOS 和 Android 平台共用得理想是个伪理想,事实上操作起来可能还不如养两个团队,反正开发外壳也是需要工程师的。

5. 更多待续