前端构建:3类13种热门工具的选型参考

35次阅读

共计 6323 个字符,预计需要花费 16 分钟才能阅读完成。

前言
在前端项目的规模和复杂性不断提升的情况下,各类构建思想和相应工具层出不穷。本文竭己所能对比了当下 13 个构建工具,包括 Browserify、Webpack、Rollup、Grunt、Gulp 和 Yeoman6 个广为流行的工具,FIS、Athena、WeFlow 和 Cooking 等 4 个国产工具,以及三大框架:React,Vue 和 Angular 的官方脚手架。希望能在项目初期的构建工具选型上为大家提供些参考。
全览
构建工具可以分为三类:模块化打包类、任务流构建类和集合型工具类(脚手架)。其中最为突出的,当属用于模块化打包的 Webpack 和用于任务流构建的 Gulp。下面是截至 2018 年 11 月 28 日某时某刻,GitHub 上各个工具的 Star 数目(听说 Star 数目可以造假?好生无聊的家伙们!)。

前端的构建一般包括 JS 转码(使用 Babel 转 ES6 或 TypeScript 自转等)、CSS 转码(Less 或 Sass 转 Css)、代码或资源的合并与压缩,基础检查和各类测试等等。这些虽与本文关系密切,但都不在讨论的范围之内。原因有二:一是实现这些功能的都是某些插件,不是工具本身,各类构建工具都是直接或间接(调用以自己的模式封装后的插件)使用它们的;二是本文介绍的是,构建方向上的类别和各类别里不同工具间的差异,与具体的操作无关。
模块化打包类
现在的前端项目基本是模块化的,原因就不在这多说。而模块化意味着分散,无法直接用于呈现,因此需要进行相应的打包形成一个整体。有些执行环境(Node)能自动打包各个模块,而有些(浏览器)则因为技术或其它考虑需要自行操作。模块化打包工具就是为模块化项目在浏览器上的优化呈现而服务的。
模块化打包的核心是:找出依赖,打包成体。各类工具的基本运行思路便是根据已有配置,从某个文件开始,递归的找出所有与其相关的依赖模块,打包成某种类型的可直接在浏览器中运行的一个或多个新文件。这之中还可以优化输出,以实现代码分离、异步加载和长效缓存等高级功能。
Browserify
官网 | GitHub
正如其官网介绍的,Browserify 会递归的分析,项目中所有使用 require 引入的 JS 模块(包括 Node 内置模块)并打包,使得 Node 类项目能在浏览器上运行。不过对于与项目有关的其它资源,比如 Css 和图片等,依然需要手动管理。虽然网上已有人编写了支持此些功能的插件,但这不仅违背了设计初衷,也使配置变得杂乱。而且对于要求越来越高的单页面应用来说,它能提供的助力着实已显疲惫。
Webpack
官网 | 中文 | GitHub
稳定版已到 v4.26.0,本文以此版本为据。另附加官方的对比文档。

Webpack 的设计思想新颖实用,社区活跃,功能强大全面,已经是针对前端各类资源的、目前最优秀的模块化管理和打包工具。它入门简单,基本的常用功能能很快上手,并用于实际开发。但精通不易,毕竟打包已是 web 开发中最重要的挑战之一,必然要耗费些许精力。学习尚且不易,介绍就更为困难,得要有一本书的厚度。所幸此节不是详细介绍,只是亮点阐述,善哉善哉。
入门已趋简单
掌握了构建的基本思路,任意工具的入门都是较为简单的(读者批:废话)。之所以强调 Webpack 入门简单,是为了减轻有意者学习之前的顾虑。一方面是它刚被推出时,由于自身的概念新颖而且文档不全面,使开发者处于懵懵懂懂的状态,总感觉离真谛还差些距离。另一方面是它的体系着实庞大,仔细想想都不免胆怯。笔者初次接触时便是这些个感受。
但现在不一样。吃土的日子已经远去,啃草的梦想还会远吗?大家准备好镰刀!
Webpack 第四版在入门上的方便性体现在三方面。一是基础功能高度集成和约定优于配置思想:安装好 Webpack 及其 CLI 后便可直接打包 JS 和 JSON 文件,与 Browserify 一样简单。二是官方文档详细(而且有基本同步的中文版),无论是概念的解析、实际运用的示例还是接口的展示都十分完备。三是现在使用和介绍 Webpack 的人已经很多了,因此网上的各路资料和相应问题的解决方案都十分丰富。你还在犹豫?
一切皆模块
如从官网上截取的图片所示,在 Webapck 眼中一切文件(.js、.css、.jpg、.woff、.csv 和.ts 等除了某些用于下载的静态大文件外)都是模块,都能通过与 JS 相似的方式被打包,并安置于合适浏览器渲染的位置。真是十分优秀的立足点。以此思想便可囊括前端会使用到的几乎所有资源,可以十分方便的统一管理和安置,更为便捷和高效。
而且此思想就是为单页面应用而生的。在 Webpack 的另一层意境中,一个 asset(各类资源)是一个模块,一个 component 是一个模块,一个 module 也是一个模块。而单页面应用的特点,不就是应用的更新不是整个页面的更新,而是某个 module 或 component 或 asset 的更新吗?十分的契合。
有人说 Webpack 的缺点在服务端渲染(或说多页面应用)上。喂喂,一来别人的目标本就不在此,二是多页面应用也不需要如此复杂的支持体系。
高效的构建性能
单页面应用或说需要构建才能展示的应用,相比多页面应用,从每次修改到重新呈现要多经历一个构建的阶段。实际操作中,如果项目庞大而构建性能不够优化,一个小小的修改(打印某值)都会消耗 5 秒以上的时间,对开发者来说真是个地狱!而优化的方法不外乎两点,一是开发者优化项目的构建思路,二是构建工具优化自身的构建性能。
Webpack 拥有较理想的构建性能。在开发阶段,当开启了 Webpack 的模块热替换之后(使用 webpack-dev-server 会自动开启),一旦检测到文件被修改,会在应用程序运行过程中通过冒泡捕获的方式最小化替换、添加或删除模块,而无需重新加载整个页面。类似 Dom 渲染中的回流:如果子元素发生的大小变化,会影响兄弟元素但不影响父元素,那么父元素及其它是无需重新绘制的。而且即便完全重新构建,也会保留先前的应用程序状态,减少等待时间。
活跃的社区
活跃的社区可以提升系统的丰富度,降低学习与使用的成本。
Webapck 社区十分活跃,应用于各种需求的插件都被一一封装而可直接使用(官方也统一展示和说明了一些常用的优秀的 Loader 和 Plugin)。不单单是其它工具的高度协调,开发中的各个阶段:搭建本地服务器、集成测试等,以及与任务流工具(Gulp、Grunt)的集成等等方面的解决或最优方案,都是丰富和全面的。基本上可以想到的需求,在这个社区中,都能直接借鉴他人已有的成果。
Rollup
官网 | 中文 | GitHub
Rollup 定位为一个 JS 模块打包器(明指 JS),主要用来构建 JS 库,也可服务于一些无需代码拆分和动态导入的小型应用程序。能在 Webpack 已稳居打包之首的情况下杀出一条血路,得到 Vue、D3、Three 和 React 等著名库的青睐,想必其着手点和性能有过人之处。
Rollup 本身结构简单,需要的配置项也不多,再加文档全面,所以很容易上手并全部掌握。它使用 ES6 本身的 Module 语法作为自己的标准,而不是诸如 CommonJS 和 AMD 等以前的解决方案。这意味着按照 Module 标准编成的代码,不仅现在可以借助 Rollup 打包运行,未来更能在实现此标准的浏览器上直接运行。
通过 Module 的特性,Rollup 开创了 Tree-shaking 功能——清除没有在项目中使用到的代码。它基于显式的 import 和 export 语句的方式,通过静态分析,排除了任何未在实际中使用的代码,能极大的减少构建于已有模块的项目体积。再加上其构建基本不添加自身的控制代码,使打包后的文件真正的达到纯净二字。想想还有点痒痒,我挠挠裆部。
与 Webpack 对比
Rollup 和 Webpack 因其定位和专注点是可以共同存在并相互支持的。
正如 Rollup 官网所说的,Rollup 更适合构建独立的 JS 库,而 Webpack 为资源丰富的应用程序。虽然 Webpack 也增加了自己的 Tree-shaking 功能,但在编译后的输出代码中,简单地运行自动 minifier 检测未使用的变量,得到的结果是不如原生的静态分析。更何况 Webpack 生成的代码一定是经过自己包装后的代码——将每个模块封装在一个函数中,再置于一个包中,通过浏览器能使用的 require 方式逐一执行这些模块。
任务流构建类
基于任务的构建行为,是不在乎操作对象是否为模块化的。
这类工具的目标是通过配置来解放日常需要重复的工作——转化、合并压缩和单元测试等等。有人说:这些操作 Webpack 和 Rollup 不是也能做?是的,基本能做。实际上,在用模块化构建工具的开发中,很少会用到任务流构建工具。但这绝不是说任务流工具会被取代,也不会被取代,至少多页面应用需要。再说任务流工具是十分纯粹的自动化行为,与模块化打包工具立足点就不一样,何谈取代一说。
Grunt
官网 | 中文 | GitHub
Grunt 虽是老牌构建工具,但依然被许多知名项目如 WordPress、Twitter 和 Jquery 等使用,也拥有持续更新的完整生态圈和中文文档。它是通过配置驱动——通过获取到的 JSON 配置执行操作,来流水线式执行相应任务。虽然在学习成本和执行效率上不出众,但如果项目原本就是通过它自动化构建的,是没有必要迁移到其它工具的。
// Grunt 的配置驱动示例
module.exports = function(grunt) {
grunt.initConfig({
jshint: {
files: [‘Gruntfile.js’, ‘src/**/*.js’, ‘test/**/*.js’],
options: {
globals: {
jQuery: true
}
}
},
watch: {
files: [‘<%= jshint.files %>’],
tasks: [‘jshint’]
}
});

grunt.loadNpmTasks(‘grunt-contrib-jshint’);
grunt.loadNpmTasks(‘grunt-contrib-watch’);

grunt.registerTask(‘default’, [‘jshint’]);

};
Gulp
官网 | 中文 | GitHub
Gulp 是新型的构建工具,虽与 Grunt 的功能相同,但其构建过程却有三大优势。
代码驱动
代码驱动即通过执行实际代码驱动程序执行,与常见的配置驱动不同(Webpack、Rollup 和 Grunt 等都是配置驱动)。从任务流构建的角度上看,代码驱动相比配置驱动有三点好处:一是高度的灵活;二是没有过多的配置项,减少学习成本;三是更方便错误的断定和异常情况的调试。
// Gulp 的代码驱动示例
gulp.src(‘./client/templates/*.jade’)
.pipe(jade())
.pipe(gulp.dest(‘./build/templates’))
.pipe(minify())
.pipe(gulp.dest(‘./build/minified_templates’));
Node 流
Gulp 作为后来者,充分利用 NodeJS 流的思想进行 IO 操作,极大增加了大型项目的构建速度。比方说转化 Scss 成 Css,Grunt 的操作流程是:读取 Scss 文件、转化成 Css、存储到磁盘,读取 Css、压缩处理最后存储到磁盘;而 Gulp 得操作是:读取 Scss 文件、转化成 Css、压缩处理最后存储到磁盘。一步到位,无需多次的 IO 操作。
简单明了
Gulp 有十分精简的 API。你能想到各种类型的任务,基本是通过仅有的五个可链式操作的方法实现的吗?不仅仅是学习和使用方便,编写后的功能也是一目了然。虽然代码驱动相比配置驱动,需要自己写的代码增加,但一是没增加难度只是函数名的多次重写,二是相对代码驱动的好处来说可以忽略。
集合型工具类
集合型工具类便是常说的脚手架,也可以看作是以模块化或任务流工具为主体的,各类常用工具的高度封装。它是一个开箱即可用的集合体,类似前后端同构时代的后端框架。它会根据你的选择,生成一个完整的、已配置好各类工具的、具有某些特定代码约定的项目框架。这些配置几乎包揽前端开发的整个流程,甚至可以集成自动化部署等后端接口。
官方框架
React CLI | Vue CLI | Angular CLI
集合型工具一般为单页面应用服务,而单页面应用需要使用某个前端框架。无论你是用 React、Vue 或 Angular,还是其它框架,首先得想到它是否有官方脚手架。比如 Vue 有 Vue CLI。一般推荐有官方脚手架的直接使用官方的。因为现代前端框架一般不单独运行,需结合官方提供的其它工具,比如路由、状态管理等。而且各个框架及配件更新不断,每次更新都可能导致与其它插件的兼容问题,新的功能可能需要某些特定插件才能发挥作用。这是一项工程,仅靠个人或某些团体很难照顾周全的。而各个框架又都有意识的通过官方脚手架来充分展示新的特性,降低学习和使用的成本。我们何乐而不为呢?
Yeoman
官网 | GitHub
Yeoman 是一个专为现代前端而生的、灵活通用的脚手架工具。
它的运作方式和其它脚手架不同。在安装好 CLI 后,需要找到一个符合要求的 Generator(一个 npm 包,相当于脚手架),使用 Yeoman 运行安装,生成初始化的项目。你也可以自行配置,使用 Yeoman 封装成符合特定需求的 Generator,并发布出去。等到下次,其他人或你自己,需要生成符合此要求的项目时,便可以直接安装并使用 Yeoman 生成。
这样有明显的两点好处:一是节省体力。在开始一个有特定需求的新项目时,如果有老项目可借鉴,一般会直接复制相关文件。但这样的复制文件可能不纯粹,即增加体积又带来安全隐患。二是在社区的支持下,很多有特殊要求的脚手架,早已有人解决并发布成 Generator,是没必要自己动手的。
国内其它
百度 – FIS – 官网 | GitHub 微信 – WeFlow – 官网 | GitHub 京东 – Athena – 官网 | GitHub 饿了么 – Cooking(名字与公司的性质相得益彰)– 官网 | GitHub
作为程序员或至各行各业,在与年龄增长速度相当的压力下,工资的高低自然成为日常性的评定标准。但在同行老友的酒桌上或某个太阳异常温煦下的小道上,能使自己为自己而不是其他事骄傲的,也肯定是“老子之前做过些什么”之类的实际付出而不是物质方面的获得。因此能够成为被公司支持的、被众多人使用的、开源框架维护团队中的程序员,多少是更为幸福的一类。
这些由国内各个前端团队开发的集合型脚手架,都是基于自用在实践中得到的最为符合本身需求的产品。里面的包含内容十分丰富,不仅仅是这以上提到的前端本职工作,还有与后端的集成方案或自动化部署配置等。且流程简化,开箱即可使用。不过这些笔者都没用过,也没有打算用。不是打趣,原因很现实,有识之士可以在文章下留言。不用却依然写出的原因倒是简单:宣传,宣传即赞许和期盼;凑数,凑到 13 种好立个多少浮夸的标题。
总结
个人观点,不喜请喷,但要和蔼可亲。
如果是使用某个前端框架开发应用程序,推荐框架官方的脚手架。如果是自己头脑发热想开源个 JS 库,推荐 Rollup 打包。如果不是模块化项目,又需要自动化处理一些事情,推荐 Gulp 作为构建工具。如果项目有特殊要求或作为核心的部件比较稀有,可以先查看 Yeoman 上是否有符合要求的 Generator,没有就只能自食其力。最后如果你处在已有自己脚手架的公司(比如饿了么),可能要按规章制度使用 Cooking 为自己的仕途烹煮些吃食。肚子真饿,这种宣传饿了么会返优惠券吗?
最后,如果是自食其力的搭建前人没有的脚手架,推荐使用 Yeoman 发布,方便你我他。

正文完
 0