前端构建工具的演变
这篇文章是我在试图搞清楚前端为何发展出这样一套巨麻烦的工具链的过程中做的笔记,在国内的社区里关于这方面的文章似乎少有讲得通透的(我没找到),最后在外网上面找到了两篇很棒的文章,推荐大家阅读:
- Modern JavaScript Explained For Dinosaurs 以我们熟悉的形式开始:html 文件引用一个 js 文件,一步步讲解为什么需要使用[npm,模块打包,babel,...]等等工具,
- NPM vs. Bower vs. Browserify vs. Gulp vs. Grunt vs. Webpack 对比各个工具,比较他们的作用,不足。(是 Stack Overflow 上的一个提问,下面的高票回答都挺好的)
首先下个定义:
构建工具:用来让我们不再做机械重复的事情,解放我们的双手的。
有哪些机械重复的事情?
在较早的前端开发中(js+css+html),有很多让我们觉得很不爽的地方,比如:
- js 的弱类型
- css 的编程性
- 手动维护依赖很麻烦
- 资源请求需要更快
- 没有热更新
- 浏览器的兼容性
......
这些需求催生出了一批前端工具,比如
ts/scss/JSMin/......
来进行以下这些工作:
- 代码检查
- 运行单元测试等
- 语言编译
- 依赖分析、打包、替换等
- 代码压缩、spirit 图片压缩等
- 版本生成
...
再进一步,一个个命令行去输入执行也是比较烦的
基于让机器代替我们手动去执行这些工作的想法,整合这些工作的构建工具出现了
首先是包管理器
包管理器
是随着 node 出现的
在没有包管理器之前,维护所使用的第三方库往往需要到官网下载包以及依赖,手动进行管理。
而包管理器包简化项目依赖项的安装和更新,不用再手动下载维护第三方包以及其依赖。
这一类工具有 npm/bower/yarn
JavaScript module bundler
//index.js
var moment = require('moment');
moment.func()
这样的代码在 node 是没有问题的,因为 node 可以访问计算机的文件系统。node 还知道每个 npm 模块路径的位置,因此无需这样写require('./node_modules/moment/min/moment.min.js)
,只需 require('moment')
而问题在于 require 浏览器是无法识别的,这就需要模块打包器
模块捆绑器从入口文件开始,查找任何 require 语句,然后将它们替换为适当的代码最后创建单个输出文件。最后在 html 中引用这个输出文件。而且把依赖打包到一个文件并且压缩可以在一定程度上解决 http 连接过多的问题
这类的工具有Browserify
webpack
task runner
我们想自动执行所有可自动化执行的任务而不是手动执行多个命令行代码,比如编译 scss,压缩代码,lint...
有些像 linux 中使用
&&
去执行一系列任务。
这类的工具有 grunt/gulp/npm
grunt/gulp
的最大不同在于:grunt
每次任务都需要读写文件。而 Gulp
基于 node stream,同时配合了一系列插件去处理流,流可以在插件之间传递。
而 npm
内置了脚本功能,通过调用其他命令行工具来执行任务。npm 再配合 webpack webpack-dev-server
eslint-loader
等等使得前端开发高效便捷且规范。
脚手架
用来创建初始项目,并且做好上面所提到的一系列配置。
如各个框架提供的 Cli 工具、Yeoman
总结
gulp、grunt、browserify、webpack、rollup 等等构建工具都通过插件的形式集成了 sass 编译成 css、图片压缩...等等功能。其中 webpack 更侧重模块(图片、js 文件、css 文件等)打包,对资源进行处理,打包成符合生产环境部署的前端资源。gulp、grunt 则旨在规范前端开发流程。如果应用场景中是打包 js 库,希望做 ES 转换,模块解析,可以使用 Rollup 相比 webpack 会更简练。