1、Grunt
Grunt 的出现早于 Gulp,Gulp 是后起之秀。他们本质都是通过 JavaScript 语法实现了 shell script 命令的一些功能。比如利用 jshint 插件实现 JavaScript 代码格式检查这一功能。早期需要手动在命令行中输入 jshint test.js,而 Grunt 则通过 Gruntfile.js 进行配置
// Gruntfile.js module.exports = function(grunt) { grunt.initConfig({ // js格式检查任务 jshint: { src: 'src/test.js' } // 代码压缩打包任务 uglify: {} }); // 导入任务插件 grunt.loadnpmTasks('grunt-contrib-uglify'); // 注册自定义任务, 如果有多个任务可以添加到数组中 grunt.regusterTask('default', ['jshint']) }
2、Gulp
Gulp 吸取了 Grunt 的优点,拥有更简便的写法,通过流(stream)的概念来简化多任务之间的配置和输出,让任务更加简洁和容易上手。Gulp 还是工具链、构建工具,可以配合各种插件做js压缩,css压缩,less编译,替代手工实现自动化工作。通过配置 gulpfile.js 文件来实现,一个简单的 gulpfile.js 配置如下
// gulpfile.js var gulp = require('gulp'); var jshint = require('gulp-jshint'); var uglify = require('gulp-uglify'); // 代码检查任务 gulp 采取了pipe 方法,用流的方法直接往下传递 gulp.task('lint', function() { return gulp.src('src/test.js') .pipe(jshint()) .pipe(jshint.reporter('default')); }); // 压缩代码任务 gulp.task('compress', function() { return gulp.src('src/test.js') .pipe(uglify()) .pipe(gulp.dest('build')); }); // 将代码检查和压缩组合,新建一个任务 gulp.task('default', ['lint', 'compress']);
好多人觉得,规则和结构都比较像,其实 gulp 本身就是借鉴了grunt 的经验进行升级和加入一些新特性。正因为流管理多任务配置输出方式的提高,人们逐渐选择使用 gulp 而放弃 grunt
3、browserify
browserify 是早期的模块打包工具,是先驱者,踏实的浏览器端使用 CommonJS 规范的格式组织代码成为可能。在这之前,因为 CommonJS 与浏览器特性的不兼容问题,更多使用的是 AMD 规范,当然后来又发展了ES6模块规范
假设有如下模块 add.js 和文件 test.js,test.js 使用 CommonJS 规范导入了模块 add.js
// add.js module.exports = function(a, b) { return a + b }; // test.js var add = require('./add.js'); console.log(add(1, 2)); // 3
我们知道,如果直接执行是执行不成功的,因为浏览器无法识别 CommonJS 语法,而 browserify就是用来处理这个问题的,他将 CommonJS 语法进行装换,在命令行执行如下
browserify test.js > bundle.js
生成的 bundle.js 就是已经处理完毕,可供浏览器执行使用的文件,只需要将它插入到<script>中即可。
4、webpack
webpack 是后起之秀,它支持了 AMD 和 CommonJS 类型,通过 loader 机制也可以使用 ES6 模块格式。还有强大的 code splitting 。webpack 还是文件打包工具,可以把项目的各种js文、css文件等打包合并成一个或多个文件,主要用于模块化方案,预编译模块的方案。webpack 是一个十分强大的工具,它正在向一个全能型的构建工具发展。
webpack 通过配置文件 webpack.config.js 进行功能配置,一个配置案例如下:
'use strict' const path = require('path') const webpack = require('webpack') const HtmlWebpackPlugin = require('html-webpack-plugin') const merge = require('webpack-merge') const utils = require('./utils') var config = { // 入口 entry: { app: './src/main.js' }, // 出口 output: { path: config.build.assetsRoot, filename: '[name].js', publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath }, // 加载器配置(需要加载器转化的模块类型) module: { rules: [ { test: '/\.css$/', use: [ 'style-loader', 'css-loader' ] } ] } // 插件 plugins: [ new webpack.DefinePlugin({ 'process.env': require('../config/dev.env') }), new webpack.HotModuleReplacementPlugin(), new HtmlWebpackPlugin({ filename: 'index.html', template: 'index.html', inject: true }), ] } module.exports = config
一个相对比较全面的配置主要包含五个部分:入口、出口、加载器、插件、模式、分别指定了开始读取文件的位置,编译后输出文件的路径,ES6语法转化加载器,更复杂功能的插件及指定执行的环境变量。
区别:
Gulp 应该和 Grunt比较,他们的区别我就不说了,说说用处吧。Gulp / Grunt 是一种工具,能够优化前端工作流程。比如自动刷新页面、combo、压缩css、js、编译less等等。简单来说,就是使用Gulp/Grunt,然后配置你需要的插件,就可以把以前需要手工做的事情让它帮你做了。
说到 browserify / webpack ,那还要说到 seajs / requirejs 。这四个都是JS模块化的方案。其中seajs / require 是一种类型,browserify / webpack 是另一种类型。
seajs / requirejs:是一种在线“编译”模块的方案,相当于在页面加载一个 CMD/AMD 解释器。这样浏览器就认识了 define、exports、module 这些东西,也就实现了模块化。
browserify / webpack:是一种预编译模块的方案,相比较上面,这个方案更加智能。没用过 browserify,这里以 webpack 为例。首先,它是预编译的,不需要在浏览器中加载解释器。另外,你在本地直接写 JS ,不管是 AMD/CMD/ES6 风格的模块化,它都能认识并且编译成浏览器认识的 JS。