为什么

前端开发为什么要进行构建,它的意义在哪?

回答这个问题之前,来先看下两个案例

案例1

  1. 未压缩的代码上线之后,因为网络请求加载很慢。
  2. 未压缩的代码请求数量过多,加载很慢。

案例2 因为案例1的教训,使用了 CDN 技术。

  1. 代码修改过之后,实际浏览器下载的还是旧的资源。
  2. 上线之前需要手动或者写脚本来替换静态资源未 CDN 地址(/a.js修改为http://cnd.com/a.js)。

接触过前端开发的同学,肯定对这两个案例颇有感触,因为这两个案例是最为常见的。

在项目比较小的时候,这些问题可以由人工手动解决;当这个项目比较大、比较多的时候,人为手动的力量就显的捉襟见肘了。由此产生了很多工具,典型的 grunt、gulp 等,就是通过维护一些指令集合来完成任务。

很明显的是,这些工具没有根本的解决问题,而是在表面上将人为的动作化为指令而已。此时,coolie 来了,在 coolie 心中,他所理解的前端构建是怎样的,不妨来看看。

做什么

前端构建做什么?

通过上面的两个案例,初步知道了前端构建需要做什么?

  1. 压缩代码
  2. 代码的版本
  3. 替换资源引用

其实很简单对不对,示意:

找到匹配的 js 文件
=> 压缩这些 js 文件到指定位置
=> 在指定位置找到这些 js 并且重命名,版本化
=> 根据文件名,找到 html 文件里的引用并且替换
=> 保存 html 文件到指定位置

其实不然,如果你这么写前端构建的话,那么你的配置将无限增大,因为你的处理过程会出现各种交错、各种串行、并行。

想一想,是不是这样呢?看看你的 gruntfile、gulpfile 是不是特别长,每次项目启动都需要安装各种 plugin。

再想一想,这些复杂、重复的操作,是不是可以归一化、通用处理呢?因为前端构建需要考虑的就只有 html、css、js 和被引用的资源,正如 ffis 官网所说。

fis项目曾经历了很久的 “努力做好编译工具” 的时代,那段时间里,fis走了很多弯路,那时我们认为前端领域需要很复杂的编译工具才能很好的处理各种开发需求。2013年初,fis的编译工具非常庞大复杂,日益暴露出来的问题已经开始不再收敛了,这促使fis小组重新审视fis的编译系统: 满足前端开发需求的最小编译规则集是什么?

前端编译工具有必要那么复杂么?答案是 完全没必要!想象一下尺规作图,一把直尺,一只圆规,就可以做出很多基本几何操作。经过fis团队不断实践总结,我们发现支持前端开发所需要的编译能力 只有三种 :

  • 资源定位:获取任何开发中所使用资源的线上路径;
  • 内容嵌入:把一个文件的内容(文本)或者base64编码(图片)嵌入到另一个文件中;
  • 依赖声明:在一个文本文件内标记对其他资源的依赖关系;

一套前端编译工具,只要实现上述3项编译能力,就可以变得非常易用,代码可维护性瞬间提高很多。

fis 的理解,和 coolie 在某种程度上有一定的不谋而合。fis 走在前列,coolie 是跟随他的脚步,更加纯粹的完成了前端构建任务:

  • JS 文件的分析、合并、压缩、版本管理
  • CSS 文件的分析、合并、压缩、版本管理
  • HTML 文件分析、压缩、版本管理
  • 入口模块的分析、分块、合并、压缩、版本管理
  • 静态资源的分析、压缩、版本管理

看到这里,可能有的朋友会说,怎么不能构建 less、scss、typeScript、ES6 呢?文章的最后会回答你。

额,我们继续。

怎么做

既然,已经知道了前端构建需要做的事情,那么就来想想该怎么做吧。

万事开头难,前端构建应该从哪开始着手呢?

首先,基础很重要,比如压缩代码、合并文件、复制文件、重命名文件、取文件的 md5、读取源代码、替换资源等。这些工具都需要在构建之前准备好。

然后,是了解任务的步骤。coolie 是这么完成的。

  1. 复制不需要构建的文件
  2. 构建模块化入口脚本(所有的入口脚本都放在指定位置)
    1. 压缩 js、css、html、image 模块的容量
    2. 处理 js、css、html、image 模块的版本
    3. js 模块引用的 html 模块里引用的 css 模块的容量、版本处理
    4. js 模块引用的 html 模块里引用的 css 模块里引用的图片的容量、版本处理
    5. 压缩模块的 ID
    6. 分离出通用模块
    7. 产生模块版本配置文件
  3. 构建 html 里的 css、js 引用
    1. html 文件的压缩
    2. html 里引用的 js、css 要进行压缩
    3. html 里引用的 js、css 要进行版本处理
    4. html 里引用的模块入口文件要版本处理
    5. html 里的 style 标签里的 css 代码,以及代码里引用的图片的容量、版本处理
  4. 分析总结
    1. 哪些入口模块没有被使用
    2. 哪些入口模块被引用而没有被构建
    3. 构建了多少文件、耗时多少

起初看起来的比较简单,只需要处理 html、js、css、静态资源就够了,而当要落地实施的时候,才发现一个构建过程竟然如此复杂?

关于 coolie 如何这些事情的,可以看看下面的这些文章:

现状

现在。已经有各种各样的前端辅助工具出现了,或大或小、或知名或无闻。而能够单独实现上述前端构建内容的,除了 coolie 之外真的基本没有其他的开源工具了。

诸如 grunt、gulp、webpack、postcss、fis 这些,基本都是一个平台(装满锤子、剪刀、钳子的工具箱)。

  • grunt:基于文件内容的基础平台。
  • gulp:基于文件流的基础平台。
  • webpack:基于文件内容分析的基础平台。
  • fis:基于文件内容分析的基础平台。
  • coolie:基于文件内容分析的构建工具。

从上至下,是前端辅助工具的发展变化,大部分都是充当了一个平台的角色。grunt、gulp、webpack、fis 这些东西,自身不能做任何事情,需要依赖各种 plugin 才能发挥作用。

当然,平台没有不好,他们有野心,总是想将所有的事情都纳入麾下。而参差不齐的 plugin 又破坏了这个美梦。通过各种 plugin 的自由组合可以实现很大的灵活性,但也增加了复杂度,无法将一个前端构建通用处理,导致目前 grunt、gulp、webpack 都没有一个比较集成、公用、公认的前端构建方案。

更为致命的是,正因为平台特征,在这些平台上的 plugin,很大一部分都是在实现编译操作。比如编译 less、scss、coffee、typeScript、es6。而这些编译操作不正是有各自预编译工具自身来处理吗?配合编辑器的 watcher,就已经做的很好了。

不是吗?这些无谓的操作,无谓的 plugin,导致了很多人对前端构建工具有一些歪曲理解和认知。开口闭口就是:

coolie 能编译 scss 吗?

现在,你知道答案了吗?

所以,这也是平台的劣势,使一些使用者误以为,前端构建就应该那样,而不是这样,以为前端构建非常的复杂,需要处理各种预编译文件才能完成。然后,你懂得之后,是不是会觉得这些东西然并卵。

以上就是配合 coolie 在前端构建中的一点点最佳实践(关于 coolie 的最佳实践,后文会说),那就是预编译交给预编译处理工具来做,资源引用就用编译后的文件。

你怎么想

coolie 还是属于新生儿,他现在已经有 1 岁有余了,还在成长的过程中,当然他也是站长巨人肩膀上才得以有今天的理解与实现。辩证的看待新事物、理智的看待国产工具、平和的看待小人物的代码,也许,你的观点会更加的客观。

那么,你怎么想?