前言
前端项目日益复杂,构建工具已经成为开发过程中不可或缺的一个部分。构建工具,说白了就是帮助我们通过配置或者编写约定好的代码,来自动完成上面的这些功能的一个工具。对于需要反复重复的任务,例如压缩、编译、单元测试、linting等,自动化工具可以减轻我们的劳动,解放我们的双手, 简化我们的工作。
时下流行的前端构建工具有 gulp 和 webpack,本文将对 gulp 和 webpack这两者做一个全面的比较。
gulp
简介
gulp是一个基于流的自动化构建工具。 除了可以管理和执行任务,还支持监听文件、读写文件。 官网描述如下:
用自动化构建工具增强你的工作流程!gulp 将开发流程中让人痛苦或耗时的任务自动化,从而减少你所浪费的时间、创造更大价值
安装
1. 安装nodejs
gulp是基于nodejs,理所当然需要安装nodejs,打开nodejs官网, 官网首页会根据系统信息选择对应版本(.msi文件),点击Download按钮,然后一路next即可安装成功。安装之后可以通过node -v查看安装的nodejs版本,出现版本号,说明刚刚已正确安装nodejs。
2. 安装gulp
使用命令行执行gulp的安装
npm install --global gulp-cli 通过gulp -v 查看安装的gulp版本,出现版本号,说明已正确安装。
实践
配置gulpfile.js文件,
gulpfile.js是gulp项目的配置文件(或者首字母大写 Gulpfile.js,就像 Makefile 一样命名)的文件,在运行 gulp 命令时会被自动加载。在这个文件中,你经常会看到类似 src()、dest()、series() 或 parallel() 函数之类的 gulp API,除此之外,纯 JavaScript 代码或 Node 模块也会被使用。任何导出(export)的函数都将注册到 gulp 的任务(task)系统中。(更多配置请查看官网)
简单的gulpfile.js配置(配置文件1)
// 导入gulp
const gulp = require('gulp');
// 定义一个print任务 (自定义任务名称)
gulp.task("print",function(){
console.log("打印123");
})
// gulp.task(name[, deps], fn) 定义任务 name:任务名称 deps:依赖任务名称 fn:回调函数
使用插件的gulpfile.js配置(配置文件2)
// 导入gulp
const gulp = require('gulp'),
less = require('gulp-less');
// 定义一个testLess任务(自定义任务名称)
gulp.task('testLess', function () {
gulp.src('src/less/index.less') // 该任务针对的文件
.pipe(less()) // 该任务调用的模块
.pipe(gulp.dest('src/css')); // 将会在src/css下生成index.css
});
// gulp.task(name[, deps], fn) 定义任务 name:任务名称 deps:依赖任务名称 fn:回调函数
// gulp.src(globs[, options]) 执行任务处理的文件 globs:处理的文件路径(字符串或者字符串数组)
// gulp.dest(path[, options]) 处理完后文件生成路径
gulp.task('default',gulp.series('testLess')); // 定义默认任务
运行gulp命令
根据配置文件1在命令行中输入gulp print,得到运行结果
根据配置文件2在命令行中输入gulp default,得到运行结果,并在src/css目录下生产index.css文件
webpack
简介
webpack 是一个打包模块化 JavaScript 的工具,在 Webpack 里一切文件皆模块,通过 Loader 转换文件,通过 Plugin 注入钩子,最后输出由多个模块组合成的文件。Webpack 专注于构建模块化项目。 其官网的首页图很形象的画出了 Webpack 是什么,如下:
安装webpack
webpack 跟 gulp 一样都是 node 包,所以在安装webpack之前依然需要安装nodejs,安装完毕后,webpack 的安装指令如下
npm install --global webpack
通过webpack -v 查看安装的webpack版本,出现版本号,说明已正确安装。
实践
配置webpack.config.js
安装完 webpack 之后在项目根目录下新建一个 webpack.config.js,这是 webpack 的默认配置文件,同 gulp 的 gulpfile.js 的功能类似。
由于 webpack 遵循 CommonJS 模块规范,因此,你可以在配置中使用(更多配置请查看官网):
- 通过 require(...) 引入其他文件
- 通过 require(...) 使用 npm 下载的工具函数
- 使用 JavaScript 控制流表达式,例如 ?: 操作符
- 对 value 使用常量或变量赋值
- 编写并执行函数,生成部分配置
基本配置
const path = require('path');
module.exports = {
mode: 'development', // 通过选择 development, production 或 none 之中的一个,来设置 mode 参数,你可以启用 webpack 内置在相应环境下的优化。其默认值为 production
entry: './foo.js', // 入口文件,告诉 webpack 你要编译哪个文件
output: { // output 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。主要输出文件的默认值是 ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中
path: path.resolve(__dirname, 'dist'),
filename: 'foo.bundle.js',
},
};
运行webpack命令
在控制台运行 webpack 命令,生成 bundle.js,编译好的文件 bundle.js 输出到了 dist 目录
对比结论
两者都是前端构建工具,gulp在早期比较流行,现在webpack相对来说比较主流,不过一些轻量化的任务还是会用gulp来处理,比如单独打包CSS文件等。
gulp是基于任务和流(Task、Stream)的。类似jQuery,找到一个(或一类)文件,对其做一系列链式操作,更新流上的数据, 整条链式操作构成了一个任务,多个任务就构成了整个web的构建流程。
webpack是基于入口的。webpack会自动地递归解析入口所需要加载的所有资源文件,然后用不同的Loader来处理不同的文件,用Plugin来扩展webpack功能。
所以总结一下:
- 从构建思路来说
gulp需要开发者将整个前端构建过程拆分成多个
Task
,并合理控制所有Task
的调用关系。 webpack需要开发者找到入口,并需要清楚对于不同的资源应该使用什么Loader做何种解析和加工。 - 对于知识背景来说 gulp更像后端开发者的思路,需要对于整个流程了如指掌 webpack更倾向于前端开发者的思路。
下表是从各个角度对 gulp 和 webpack 做的对比:
gulp | webpack | |
---|---|---|
分类 | 基于流的自动化构建工具。 | 模块化加载器兼打包工具。 |
目标 | 自动化和优化开发工作流,为通用 website 开发而生。 | 通用模块打包加载器,为移动端大型 SPA 应用而生。 |
上手难易程度 | 易于学习,易于使用,api总共只有5个方法。 | 有大量新的概念和api,不过好在有详尽的官方文档。 |
适用场景 | 基于流的作业方式适合多页面应用开发。 | 一切皆模块的特点适合单页面应用开发。 |
构建方式 | 对输入(gulp.src)的 js,ts,scss,less 等源文件依次执行打包(bundle)、编译(compile)、压缩、重命名等处理后输出(gulp.dest)到指定目录中去,为了构建而打包。 | 对入口文件(entry)递归解析生成依赖关系图,然后将所有依赖打包在一起,在打包之前会将所有依赖转译成可打包的 js 模块,为了打包而构建。 |
使用方式 | 常规 js 开发,编写一系列构建任务(task)。 | 编辑各种 JSON 配置项。 |
优点 | 适合多页面开发,易于学习,易于使用,接口优雅。 | 可以打包一切资源,适配各种模块系统 |
缺点 | 在单页面应用方面输出乏力,而且对流行的单页技术有些难以处理(比如 Vue 单文件组件,使用 gulp 处理就会很困难,而 webpack 一个 loader 就能轻松搞定) | 不适合多页应用开发,灵活度高但同时配置很繁琐复杂。“打包一切” 这个优点对于 HTTP/1.1 尤其重要,因为所有资源打包在一起能明显减少浏览器访问页面时的资源请求数量,从而减少应用程序必须等待的时间。但这个优点可能会随着 HTTP/2 的流行而变得不那么突出,因为 HTTP/2 的多路复用可以有效解决客户端并行请求时的瓶颈问题。 |
结论 | 浏览器多页应用(MPA)首选方案 | 浏览器单页应用(SPA)首选方案 |