一 概念介绍
gulp 是 task runner,Webpack 是 module bundler。可以这么说, Webpack 和 gulp 本身都有 95% 的功能是不能被对方替代,或者直接说和对方不重叠的。
1 什么是gulp
Gulp就像是一个产品的流水线,整个产品从无到有,都要受流水线的控制,在流水线上我们可以对产品进行管理
1.1 gulp的核心功能:
- 任务定义和组织;
- 基于文件 stream 的构建;
- 插件体系;
gulp适用于任何JavaScript的场合,就类似一个大的管理框架,其中的任务,与任务需要的工具都要手动去编写与引入,对整体的一个把控
2 什么是webpack
Webpack类似于一个模块打包机 可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。体现出的意义就是:一切皆模块 通过 loader的转换,任何形式的资源都可以视作模块,比如 CommonJs 模块、AMD 模块、ES6 模块、CSS、图片、JSON、Coffeescript、LESS 等。
2.1 webpack的核心功能
- 按照模块的依赖构建目标文件;
- loader 体系支持不同的模块;
- 插件体系提供更多额外的功能;
二 Gulp和Webpack功能实现对比
主要从以下方面对两种框架做一下对比
1 概念上
Gulp侧重于前端开发的整个过程的控制管理(像是流水线),我们可以通过给gulp配置不通的task(通过Gulp中的gulp.task()方法配置,比如启动server、sass/less预编译、文件的合并压缩等等)来让gulp实现不同的功能,从而构建整个前端开发流程。
Webpack有人也称之为模块打包机,由此也可以看出Webpack更侧重于模块打包,当然我们可以把开发中的所有资源(图片、js文件、css文件等)都可以看成模块,最初Webpack本身就是为前端JS代码打包而设计的,后来被扩展到其他资源的打包处理。Webpack是通过loader(加载器)和plugins(插件)对资源进行处理的。
另外我们知道Gulp是对整个过程进行控制,所以在其配置文件(gulpfile.js)中配置的每一个task对项目中该task配置路径下所有的资源都可以管理。
比如,对sass文件进行预编译的task可以对其配置路径下的所有sass文件进行预编译处理:
gulp.task('sass',function(){
gulp.src('src/styles/*.scss')
.pipe(sass().on('error',sass.logError))
.pipe(gulp.dest('./build/prd/styles/'));//编译后的输出路径
});
Webpack则不是这样管理资源的,它是根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源(如下图)。
- 需要把各种资源(js/ts/css/html/ejs/img/fonts等等)都看成 module;
- module之间必须是互相依赖的,在 js 里 import 模板、图片、样式文件等等,样式文件通过 url()和图片字体关联;这种依赖关系必须是 webpack 既定的或者是通过插件可以理解的关系。
Webpack 的核心就是模块化地组织,模块化地依赖,然后模块化地打包。相对来上,场景局限在前端模块化打包上;虽然用 gulp + 插件的方式也能实现,但目前看 Webpack 在依赖的模块化构建上是无人能够替代的。
通俗的说,Webpack就是需要通过其配置文件(webpack.config.js)中entry配置的一个入口文件(JS文件)
entry: {
app:__dirname + "/src/scripts/app.js",
}
然后Webpack进入该app.js文件进行解析,app.js
//引入scss文件
import '../style/app.scss';
//引入依赖模块
var greeter = require('./Greeter.js');
document.getElementById('root').appendChild(greeter());
解析过程中,发现一个app.scss文件,然后根据webpack.config.js配置文件中的module.loaders属性去查找处理.scss文件的loader进行处理,处理app.scss文件过程中,如果发现该文件还有其他依赖文件,则继续处理app.scss文件的依赖文件,直至处理完成该“链路”上的依赖文件,然后又遇到一个Greeter.js模块,于是像之前一样继续去查找对应的loader去处理...
所以,Webpack中对资源文件的处理是通过入口文件产生的依赖形成的,不会像Gulp那样,配置好路径后,该路径下所有规定的文件都会受影响。
2 模块化开发
概念:其实就是利用CommonJS、AMD、CMD等方式对静态资源文件进行引入管理,然后最终发布时达成相应的模块依赖包,就是为了将代码进行解耦合
先来看下gulp
Gulp
|——dist: 项目输出路径
| |——module: 开发模块(遵循就近依赖原则)
| |——index: 首页模块
| |——my: 我的模块
|——commons: 公用静态文件
|——src: 工作目录
| |——module: 开发模块(遵循就近依赖原则)
| |——index: 首页模块
| |——action_.js: 开发js(es6语法)
| |——**.scss: sass模板语言
| |——vue**.js: vue模板
| |——my: 我的模块
|——gulpfile.js: gulp的配置文件
|——index.html: 主页html文件
|——package.json: npm包管理配置文件
然后通过编写task命令对 文件进行css转译,js压缩/转译,img,html压缩等等操作
webpack目录
主要对entry入口文件中所有的依赖以及后续依赖进行分析,对公共文件进行抽取分离压缩打包
3 开发过程中的依赖导入
gulp中大部分静态文件都是已经标签化插入好的(如果js文件中使用import和require的es6语法,打包还要另外加入插件plugin和browserify,与其这样像webpack靠拢不如直接拿来webpack配置各司其职,相互配合,这也是一种gulp+webpack的模式)
webpack 可以随用随插,按需加载(gulp中目前我使用的是require--采用强依赖模式已经把需要的模块提前注入好了)和打包
所以就方便程度和学习成本来说,webpack更胜一筹
4 进行可视化打包分析
gulp还没尝试过,不知道相关插件能否做到,不过webpack由于社区比较活跃,对应的可视化分析插件很多,其中一个就是
npm install --save-dev webpack-bundle-analyzer
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
// ...
plugins: [new BundleAnalyzerPlugin()]
// ...