大家好,很高兴又见面了,我是"高级前端?进阶?",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
前言
在 JavaScript 领域,技术进步飞快。 大多数现代应用程序都是使用 Vue.js 和 React 等技术构建的,并使用了 Webpack 等模块打包器。
然而,实际上,许多项目并不需要像 Webpack 这样的成熟模块打包器,但仍然需要一种方法来编译其前端资源。 从一定程度上讲,Webpack 并非设计为任务运行器,因此在不打包模块的情况下将其配置为构建资产并不容易。 因此,像 Grunt 和 Gulp 这样的任务运行程序仍然占有一席之地。
1.Gulp/Grunt被Webpack彻底取代了么?
Grunt /Gulp与Webpack的区别主要集中在以下几个点:
- Gulp/Grunt 是一个任务运行器,而 Webpack 是一个打包器,可以为用户打包代码。 因此,Webpack 可以在不借助任何其他应用程序的情况下自行运行大部分功能。
- Webpack 可以用作中间件,监控系统的任务。 这是在称为 webpack-dev-server 的开发环境中的服务器帮助下完成的,该服务器管理重新加载、热加载。 而 Gulp/Grunt没有这些能力,因为所有工作都被设计为任务。
- Gulp 中发现错误比在 Webpack 中更难。 在 Webpack 中,很容易找到未运行的代码并在不需要时将其删除,比如死代码消除。 但、Gulp/Grunt 不具备这种能力。
- Webpack 是一个高级构建系统,会管理文件变更,如果任务在第一次尝试中不起作用,则会重新运行。 Gulp 只能管理单个应用程序,它永远不是 Webpack 的替代品,而 Webpack 可以作为 Gulp 的替代品。
总体来看,Gulp/Grunt 作为一个任务运行器有一定的适用场景,而且以前很多云构建脚本都是基于它们编写。Webpack要完全替换Gulp/Grunt可能还需要一定的时间。本文将重点研究 Grunt 和 Gulp, 以了解它们的限制。
值得注意的是,由于Grunt/Gulp/Webpack都使用 JavaScript,因此用户在从 Gulp 迁移到 Webpack 时不会有任何不适应。
2.Gulp vs Grunt有何不同?
在了解这些构建工具有何不同之前,值得注意的是它们都被设计来做同样的事情:自动化原本必须手动完成的任务。 这些任务包括:
- 将 Less/Sass 编译为 CSS
- 连接和压缩 CSS 和 JavaScript
- linting 代码
- 优化图像
- 运行单元测试等等
这两种工具都可以帮助开发自动编译前端资产,并使构建结果保持一致而且更加可靠,而这一切都是通过社区贡献的插件来完成的。 在撰写本文时,Grunt 插件注册表包含 6,250 个插件,而 Gulp 插件注册表包含 4000 多个不同的插件。 尽管 Grunt 在这方面处于领先地位,但两者的数量都相当可观。
3.Grunt 和 Gulp 是如何工作的?
Grunt 通过在名为 Gruntfile.js 的文件中定义任务来工作,该文件的结构与 JSON 非常相似。 可以为每个任务指定配置,Grunt 将按顺序运行这些任务。 该文件易于阅读和理解,这使得 Grunt 可能是这两个构建工具中更直观的一个。
另一方面,Gulp 通过使每个任务定义成为一个在名为 Gulpfile.js 的文件上声明的 JavaScript 函数来关注“代码优于配置”原则。 Gulp 代码通常比 Grunt 代码短得多,因为预先不涉及配置。 然后,开发者可以将函数链接在一起,并行或串行运行,以创建构建脚本。
一大优势是 Gulp 可以利用节点流,这意味着 Gulp 不必将中间文件写入磁盘。 这样做的结果是 Gulp 通常比 Grunt 快得多,但由于使用流和Promise,学习曲线可能稍微陡峭。
构建脚本
比较Grunt与Gulp 的最简单方法是使用每种工具创建相同的构建脚本比较配置文件和性能。
下面创建一个 Gruntfile.js 和一个 Gulpfile.js,它们都执行以下操作:
- 将 Sass 文件编译成 CSS
- 连接和缩小 CSS 和 JavaScript
- 优化图像
首先,确保机器上同时安装了 Grunt 和 Gulp CLI:
npm install -g grunt-cli gulp-cli
接下来安装运行 Grunt 和 Gulp 所需的包。可以通过运行 npm install {package} --save-dev 或将以下行复制到 package.json 并运行 npm install 来手动执行此操作:
{
"name": "grunt-vs-gulp-demo",
"version": "1.0.1",
"devDependencies": {
// 安装依赖
"grunt": "^1.1.0",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-cssmin": "^3.0.0",
"grunt-contrib-imagemin": "^4.0.0",
"grunt-contrib-uglify": "^4.0.1",
"grunt-sass": "^3.1.0",
"gulp": "^4.0.2",
"gulp-clean-css": "^4.3.0",
"gulp-concat": "^2.6.1",
"gulp-imagemin": "^7.1.0",
"gulp-sass": "^4.1.0",
"gulp-stats": "0.0.4",
"gulp-uglify": "^3.0.2",
"node-sass": "^4.14.1",
"time-grunt": "^2.0.0"
}
}
对于 Grunt,需要在项目的根目录中创建一个 Gruntfile.js。
//Gruntfile.js内容
module.exports = function (grunt) {
const sass = require('node-sass');
const mozjpeg = require('imagemin-mozjpeg');
require('time-grunt')(grunt);
grunt.initConfig({
sass: {
options: {
implementation: sass
},
dist: {
files: {
'dist-grunt/css/style.css': 'assets/scss/style.scss'
}
}
},
concat: {
// concat操作
css: {
files: {
'dist-grunt/css/styles.css': [
'dist-grunt/css/style.css',
'assets/css/test.css'
],
},
},
js: {
files: {
'dist-grunt/js/scripts.js': [
'assets/js/test1.js',
'assets/js/test2.js'
],
},
},
},
cssmin: {
dist: {
files: {
'dist-grunt/css/styles.min.css': ['dist-grunt/css/styles.css']
}
}
},
uglify: {
// 压缩js
dist: {
files: {
'dist-grunt/js/scripts.min.js': ['dist-grunt/js/scripts.js']
}
}
},
imagemin: {
// 压缩图片
dynamic: {
options: {
optimizationLevel: 5,
use: [mozjpeg()]
},
files: [{
expand: true,
cwd: 'assets/img/',
src: ['**/*.{png,jpg,gif}'],
dest: 'dist-grunt/img'
}]
}
}
});
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-imagemin');
grunt.registerTask('default', ['sass', 'concat', 'cssmin', 'uglify', 'imagemin']);
};
Grunt 任务的配置不是很有表现力,但相当容易理解。 此外,因为 Grunt 按顺序运行任务,可以对诸如文件可用之类的事情做出安全的假设(例如,dist-grunt/css/style.css 已在运行 concat 任务之前编译)。
对于 Gulp,需要在项目的根目录中创建一个 Gulpfile.js。
//Gulpfile.js文件内容
const gulp = require('gulp');
const sass = require('gulp-sass');
const concat = require('gulp-concat');
const cleanCSS = require('gulp-clean-css');
const uglify = require('gulp-uglify');
const imagemin = require('gulp-imagemin');
sass.compiler = require('node-sass');
function scss() {
return gulp.src('assets/scss/**/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('dist-gulp/css'));
}
function css() {
return gulp.src([
'dist-gulp/css/style.css',
'assets/css/test.css'
])
.pipe(concat('styles.css'))
.pipe(gulp.dest('dist-gulp/css'))
.pipe(concat('styles.min.css'))
.pipe(cleanCSS())
.pipe(gulp.dest('dist-gulp/css'));
}
function js() {
return gulp.src('assets/js/**/*.js')
.pipe(concat('scripts.min.js'))
.pipe(uglify())
.pipe(gulp.dest('dist-gulp/js'));
}
function img() {
return gulp.src('assets/img/*')
.pipe(imagemin([
imagemin.mozjpeg({optimizationLevel: 5})
]))
.pipe(gulp.dest('dist-gulp/img'));
}
exports.default = gulp.parallel(gulp.series(scss, css), js, img);
// 并行运行
Gulp的配置更具表现力,允许开发者以更合乎逻辑的方式进行分组。 同样由于 Gulp 的流实现,每个任务都可以并行运行,这是它比 Grunt 快得多的原因。
但是,需要注意的是要确保不会破坏任何依赖链。 为防止这种情况,可以定义要连续运行的任务,就像 scss 和 css 任务一样,从而可以确保 dist-gulp/css/style.css 在 css 任务需要它时已经编译好了。
4.Gulp和Grunt性能对比
4.1 Grunt
4.2 Gulp
- Grunt 任务:1.6 秒
- Gulp 任务:0.84 秒
这些结果并不令人惊讶,但它确实表明 Gulp 比 Grunt 快多少。在小项目中,大约 800 毫秒的差异可能不是什么大问题。 然而,对于大型项目,速度差异会成倍增加,Grunt 最终可能会慢得多。
5.Gulp vs. Grunt vs. Webpack
Gulp和Grunt确实火了很长一段时间,那时候代码构建几乎都是依靠它们完成。但是最近几年仿佛已经销声匿迹,前端已经很少提及它们。而这一切的原因一方面是技术上的,这一点在文章前面已经说过了Gulp和Grunt的诸多局限性,但是另一方面确实是因为很多优秀竞争者的出现,比如文章提及的Webpack。接下来就从各种数据一探究竟!
先看看本文的主角,对Gulp和Grunt做一个简单对比。Github数据表明,Gulp的star有32k,而Grunt只有12k,两者项目开源时间都已经长达10年(Grunt短一年),从这一点上看Gulp明显会优于Grunt。
下面再看看下载量的对比,以过去一年的下载数据来看。不论是Gulp还是Grunt,两者的使用量已经非常稳定,几乎没有增长的趋势,当然也没有下降趋势。而且Gulp的数据表现依然优于Grunt、与Github的数据指标表现一致。
接下来将Webpack加进来,一起对比下三者的数据。由于Webpack的加入,Gulp瞬间被抢去了主角光环,Github的数据显示Webpack的star已经有62k,远远高于Gulp的32k,而且三种项目周期几乎一致。
从过去一年的下载量来看,Gulp/Grunt也瞬间被Webpack秒杀,而且差距不是一点半点(具体查看下图)。根据最近的NPM下载数据,周下载量Webpack(22636k) > Gulp(1180k) > Grunt(673k),而且差距非常大。
从数据上看,属于Gulp和Grunt的时代已经过去了,新的百家争鸣时代又来了。Vite、Webpack、Turbopack等等,谁又是下一个Gulp和Grunt呢?大家拭目以待!
6.本文总结
本文主要和大家介绍下Grunt 、 Gulp与Webpack。文章从Grunt/Gulp与Webpack区别 、Gulp vs Grunt有何不同 、Grunt 和 Gulp 如何工作、Gulp和Grunt性能对比等几个角度展开。相信通过本文的比较,大家对选择Grunt/Gulp还是Webpack都已经比较清楚了。因为篇幅有限,如果有兴趣,文末的参考资料提供了大量优秀文档以供学习。
参考资料
https://deliciousbrains.com/grunt-vs-gulp-battle-build-tools/
https://www.keycdn.com/blog/gulp-vs-grunt
https://www.educba.com/gulp-vs-webpack/