Webpack和Gulp对比

Webpack和Gulp对比

144 
做者 彬_仔 
2016.10.19 22:42* 字数 8012 阅读 2471评论 18

在如今的前端开发中,先后端分离、模块化开发、版本控制、文件合并与压缩、mock数据等等一些本来后端的思想开始逐渐渗透到“大前端”的开发中。前端开发过程愈来愈繁琐,当今愈来愈多的网站已经从网页模式进化到了 Webapp 模式。它们运行在现代的高级浏览器里,使用 HTML五、 CSS三、 ES6 等更新的技术来开发丰富的功能,网页已经不只仅是完成浏览的基本需求,而且Webapp一般是一个单页面应用(SPA),每个视图经过异步的方式加载,这致使页面初始化和使用过程当中会加载愈来愈多的 JavaScript 代码,这给前端开发的流程和资源组织带来了巨大的挑战。javascript

前端开发和其余开发工做的主要区别,首先是前端是基于多语言、多层次的编码和组织工做,其次前端产品的交付是基于浏览器,这些资源是经过增量加载的方式运行到浏览器端,如何在开发环境组织好这些碎片化的代码和资源,而且保证他们在浏览器端快速、优雅的加载和更新,就须要一个模块化系统,这个理想中的模块化系统是前端工程师多年来一直探索的难题。css

本文须要有必定的GulpWebpack的基本概念,对Gulp和Webpack的使用有必定的了解。
同时还须要对npm或者cnpm有必定的的了解,对ComonJS、AMD规范有必定的的了解。html

Gulp

Gulp就是为了规范前端开发流程,实现先后端分离、模块化开发、版本控制、文件合并与压缩、mock数据等功能的一个前端自动化构建工具。说的形象点,“Gulp就像是一个产品的流水线,整个产品从无到有,都要受流水线的控制,在流水线上咱们能够对产品进行管理。”前端

另外,Gulp是经过task对整个开发过程进行构建。java

Webpack

Webpack 是当下最热门的前端资源模块化管理和打包工具。它能够将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还能够将按需加载的模块进行代码分隔,等到实际须要的时候再异步加载。经过 loader的转换,任何形式的资源均可以视做模块,好比 CommonJs 模块、AMD 模块、ES6 模块、CSS、图片、JSON、Coffeescript、LESS 等。node

Gulp和Webpack功能实现对比

简单介绍了一下Gulp和Webpack的概念性的问题和大环境,接下来进入本文的主题,对比一下Gulp和Webpack的优缺点。将从基本概念、启动本地Server、sass/less预编译、模块化开发、文件合并与压缩、mock数据、版本控制、组件控制八个方面对Gulp和Webpack进行对比。react

基本概念

首先从概念上,咱们能够清楚的看出,Gulp和Webpack的侧重点是不一样的。webpack

Gulp侧重于前端开发的整个过程的控制管理(像是流水线),咱们能够经过给gulp配置不通的task(经过Gulp中的gulp.task()方法配置,好比启动server、sass/less预编译、文件的合并压缩等等)来让gulp实现不一样的功能,从而构建整个前端开发流程。git

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/'));//编译后的输出路径 });

上面这个task能够对'src/styles/*.scss'目录下的全部以.scss结尾的文件进行预处理。

Webpack则不是这样管理资源的,它是根据模块的依赖关系进行静态分析,而后将这些模块按照指定的规则生成对应的静态资源(以下图)。


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那样,配置好路径后,该路径下全部规定的文件都会受影响。

模块化开发

所谓的前端模块化开发,个人理解就是,在开发的时候,把不通的资源文件按照他的具体用途进行分类管理,在使用的时候利用CommonJS、AMD、CMD等规范将这些资源文件引入到当前文件中。而后在测试或者最后上线的时候,将这些资源文件按照必定的要求进行压缩合并再加上版本控制处理。
可能这样的理解或者说法值得商榷,可是我的仍是以为模块化就是对内容的管理,是为了解耦合。

首先从Gulp入手,看看在项目中,怎样利用模块化的思想进行开发。下面是一个gulp项目的目录结构:


gulp项目目录结构
Gulp
   |——build: 项目输出路径 | |——prd: css、js文件输出路径 | |——scripts: js文件的输出路径 | |——styles: css文件的输出路径 | |——ver: 版本号相关文件 | |——index.html: 编译后的index.html |——images: 图片文件夹 |——mock: mock数据文件夹 |——node_modules: npm包管理文件夹 |——src: 工做目录 | |——scripts | |——libs: 第三方依赖库(jQuery等) | |——tpls: 模板文件 | |——utils: 工具类文件夹 | |——views: 页面自定义js文件 | |——app.js: index.html文件的入口js | |——styles:文件和scripts文件夹下基本一致(本例中我引用了第三方框架,目录更深,不在展现) |——gulpfile.js: gulp的配置文件 |——index.html: 主页html文件 |——package.json: npm包管理配置文件

在实际开发过程当中,在src目录下工做,html、js和css等文件经过gulp的task配置,执行合并和压缩后输出到build目录下(下面会详细介绍合并压缩的实现)。在详细一点就是:

  1. 建立主页html文件
  2. 建立与之对应的app.js入口文件和app.scss入口文件。这两个文件只经过CommonJS规范引入各自views文件中自定义的js(或scss)文件,具体逻辑不写此文件中。
  3. 在views目录下编写js(或css)文件的逻辑代码,其中若是多个文件须要公共逻辑或者工具方法,就能够抽离出来在util文件夹下建立对应的公共方法,而后在views中须要的js(或css)文件中经过CommonJS规范引入使用。libs目录下的第三方库或框架也是这个思想去引用。
  4. scripts目录下的tpls文件是用来放置html模板的,引用方式和引用libs相同。

大致介绍了一下我理解的模块化的思想,可是须要指出的是Gulp对js文件的模块化工做是经过Webpack实现的,具体来讲是经过安装gulp-webpack模块和相关的loader模块进行js模块化管理的。具体步骤以下:

  1. 在项目中经过npm安装一个gulp-webpack、vinyl-named、imports-loader和string-loader模块(压缩合并模块后面再介绍)
    $ npm install gulp-webpack vinyl-named -D
  2. 而后在Gulp的配置文件gulpfile.js中经过CommonJs规范引入gulp-webpack 模块,并进行简单配置

    //1.引入 gulp-webpack和vinyl-named模块 var webpack= require('gulp-webpack'); var webpack= require('vinyl-named'); //2.js 模块化配置 var jsFiles = [ './src/scripts/*.js', ]; gulp.task('packjs',function(){ gulp.src(jsFiles) .pipe(uglify().on('error',function(err){ console.log('\x07',err.lineNumber,err.message); return this.end(); })) //Webpack 对js模块化部分 start .pipe(webpack({ output:{ filename:'[name].js' }, module:{ loaders:[{ test: /\.js$/, loader:'imports?define=>false' }, { test:/\.string$/, loader:'string' } ] } })); //Webpack 对js模块化部分 end .pipe(concat('all.js')) .pipe(gulp.dest('./build/prd/scripts/')); });

对css文件咱们也采用同js文件同样的模块化思想,利用sass进行模块化开发,至于对scss文件的合并压缩配置,下面还会详细介绍。

接下来应该介绍一下Webpack的模块化实现了,其实也就没什么能够说的了,文件目录和Gulp的基本相同,只不过实现过程当中使用到的插件或者说模块不一样,配置不一样而已。另外须要注意的是,Webpack对于资源文件的模块化打包处理都是按js文件的处理方式处理的,例如仍是上一小节中,你可能发现了,我在app.js入口文件中有这样一行代码

import '../style/app.scss';

你当时可能产生疑问,为何在js文件中引入scss文件呢?
这是由于Webpack是经过依赖关系进行文件管理的,因此,想要对样式文件进行模块化管理则必须与app.js入口文件创建依赖关系,所以咱们将样式文件的入口app.scss文件引入到了app.js中(其余资源想要被管理,也须要这样与app.js入口文件创建依赖关系)。
可是这样作很明显的就是样式文件经过app.js入口文件所有都合并压缩到js文件中了,这很显然不是咱们想要的结果,因此咱们须要将样式文件从js文件中剥离出来。

  1. 在项目中经过npm安装一个extract-text-webpack-plugin的模块
    $ npm install extract-text-webpack-plugin -D
  2. 而后在Webpack的配置文件webpack.config.js中进行简单配置

    //1.引入extract-text-webpack-plugin模块 var Et = require('extract-text-webpack-plugin'); module.exports = { //source-map调试 devtool: 'eval-source-map', //webpack入口文件配置 entry: { app:__dirname + "/src/scripts/app.js", }, //webpack出口文件配置 output: { path: __dirname + "/prd/scripts/",//输出文件路径配置 filename: "bundle.js"//输出文件名配置 }, module:{ loaders:[ { test: /\.scss$/, loader: Et.extract('style','css!sass')//从js中抽离scss文件 } ] }, plugins: [ new Et('./styles/bundle.css'),//从js中抽离scss文件输出目录设置 ], //本地server配置 devServer: { contentBase: __dirname + '/prd/',//本地服务器所加载的页面所在的目录 port:8089,//本地服务端口配置 colors: true,//终端中输出结果为彩色 historyApiFallback: true,//不跳转 inline: true//实时刷新 } }

    上面有些配置信息并不彻底,下面的小节中会逐渐介绍到。这样咱们就实现了将css文件从js文件中剥离出来的目的。Webpack不但能够对css文件能够进行模块化管理,还能够对图片进行模块管理,有兴趣的能够本身去尝试一下。

文件合并与压缩

上面的模块化中,咱们提到了模块化其实很大一部分是在作文件的合并与压缩操做,因此咱们立刻来看看Gulp和Webpack是怎样是想文件的合并和压缩的。

先来看看大背景,因为如今前端愈来愈庞大,页面文件依赖也愈来愈多,因此对这些文件进行合理的合并和压缩就志在必得。根据前面的了解,Webpack应该比Gulp更擅长文件合并和压缩,毕竟人家被称为模块打包机吗。
结论是正确的,Gulp能够对css文件以及js文件进行合并压缩处理,而Webpack能够实现对css文件,js文件,html文件等进行合并压缩和图片的压缩,还能够对js文件进行编译(如es6-->es5,react jsx)等等,这些都是经过Webpack的loader实现的,固然这些也能够加入到Gulp中,毕竟Gulp把Webpack当作一个模块,经过gulp-webpack都引入了。

Gulp合并压缩文件

css的压缩

要想实现Gulp对css文件的压缩只须要安装一个gulp-minify-css模块便可。

  1. 在项目中经过npm安装一个gulp-minify-css的模块
    $ npm install gulp-minify-css -D
  2. 而后在Gulp的配置文件gulpfile.js中经过CommonJs规范引入gulp-minify-css模块,并进行简单配置

    //1.引入 gulp-minify-css模块 var minifyCSS = require('gulp-minify-css'); //2.css 预处理 var cssFiles = [ './src/styles/usage/page/index.scss' ] gulp.task('sass',function(){ gulp.src(cssFiles) .pipe(sass().on('error',sass.logError)) .pipe(minifyCSS())//执行压缩处理在一行 .pipe(gulp.dest('./build/prd/styles/')); });

    这样一个简单的css压缩就实现了。

js合并压缩

要想实现Gulp对js文件的合并压缩须要安装一个gulp-uglify和gulp-concat两个模块,前者是用于压缩的模块,后者是一个合并的模块。

  1. 在项目中经过npm安装gulp-uglify和gulp-concat模块
    $ npm install gulp-uglify gulp-concat -D
  2. 而后在Gulp的配置文件gulpfile.js中经过CommonJs规范引入gulp-uglify和gulp-concat模块,并进行简单配置

    //1.引入**gulp-uglify**和**gulp-concat**模块 var uglify = require('gulp-uglify'); var concat = require('gulp-concat'); //js 合并压缩 var jsFiles = [ './src/scripts/*.js', ]; gulp.task('packjs',function(){ gulp.src(jsFiles) //js文件的压缩 .pipe(uglify().on('error',function(err){ console.log('\x07',err.lineNumber,err.message); return this.end(); })) .pipe(webpack({ output:{ filename:'[name].js' }, module:{ loaders:[{ test: /\.js$/, loader:'imports?define=>false' }, { test:/\.string$/, loader:'string' } ] } })); //js文件的合并 .pipe(concat('all.js')) .pipe(gulp.dest('./build/prd/scripts/')); });

    js的文件合并压缩也完成了。咱们再来看一下Webpack的合并压缩。

Webpack的合并压缩

压缩js和css

针对js和css文件的压缩,Webpack已经内嵌了uglifyJS来完成对js与css的压缩混淆,无需引用额外的插件。咱们只须要在Webpack配置文件中的plugins属性中作以下配置:

plugins: [ new webpack.optimize.UglifyJsPlugin({ //压缩代码 compress: { warnings: false }, except: ['$super', '$', 'exports', 'require'] //排除关键字 }) ]

须要注意的是:压缩的时候须要排除一些关键字,不能混淆,好比$或者require,若是混淆的话就会影响到代码的正常运行。

html的压缩

想要对html进行压缩,一样也是须要配置Webpack的配置文件,而且须要下载两个插件HtmlWebpackPlugin和html-minifier插件:
1.在项目中经过npm安装HtmlWebpackPlugin和html-minifier模块

$ npm install HtmlWebpackPlugin -D $ npm install html-minifier -D

2.而后在Webpack的配置文件webpack.config.js进行以下配置:

plugins: [ new HtmlWebpackPlugin({ //根据模板插入css/js等生成最终HTML favicon:'./src/img/favicon.ico', //favicon路径 filename:'/view/index.html', //生成的html存放路径 template:'./src/view/index.html', //html模板路径 inject:true, //容许插件修改哪些内容,包括head与body hash:true, //为静态资源生成hash值 minify:{ //压缩HTML文件 removeComments:true, //移除HTML中的注释 collapseWhitespace:true //删除空白符与换行符 } }) ]

HtmlWebpackPlugin插件在生成HTML时调用了 html-minifier 插件来完成对HTML的压缩,这里咱们使用两个配置完成来移除HTML中的注释以及空白符达到压缩的效果。

sass/less预编译

咱们再来看看sass/less预编译,其实就sass/less的预编译来讲,二者区别不是很大。Gulp是经过gulp-sassgulp-less模块进行预处理;而Webpack是经过scss-loaderless-loader加载器(loader)进行预处理。咱们仍是分别来看一下二者对此的实现。

Gulp预编译sass/less

以sass为例子:

  1. 在项目中经过npm安装一个gulp-sass的模块
    $ npm install gulp-sass -D
  2. 而后在Gulp的配置文件gulpfile.js中经过CommonJs规范引入gulp-sass模块,并进行简单配置

    //1.引入 gulp-sass模块 var sass= require('gulp-sass'); //2.css 预处理 var cssFiles = [ './src/styles/usage/page/**/*' //./src/styles/usage/page目录下的全部文件 ]; gulp.task('sass',function(){ gulp.src(cssFiles) .pipe(sass().on('error',sass.logError)) .pipe(minifyCSS()) .pipe(gulp.dest('./build/prd/styles/'));//编译后的输出路径 }); //3.对sass文件的修改添加监听事件 gulp.task('watch',function(){ gulp.watch('./src/styles/**/*',['sass']); }); gulp.task('default',['watch','webserver'],function(){ console.log('全部任务队列执行完毕'); });

    这样,一个简单的sass预处理的task就配置完成了,而后咱们还将该task加到gulp.watch()上实现了自动编译(即修改sass文件后保存,则当即执行sass预处理),配合Gulp启动的server则能够实现sass文件修改保存便可在浏览器中查看效果的目的,下一小节会介绍启动本地server。

Webpack预编译sass/less

一样以sass为例子:

  1. 在项目中经过npm安装一个sass-loader和node-sass模块,前者是用来加载sass相关文件的,后者是用来编译sass文件的。另外还须要安装另外两个模块css-loader和style-loader,前者是用来加载css相关文件的,后者是用来将css样式装填到html中的内联样式。
    $ npm install sass-loader node-sass css-loader style-sass -D
  2. 而后在Webpack的配置文件webpack.config.js中进行简单配置
    module:{ loaders:[ { test: /\.css$/,//匹配以.css结尾的文件,若是你项目不须要刻意不配置 loader: 'style!css'//这里顺序必须这样 }, { test: /\.scss$/,//匹配以.scss结尾的文件 loader: 'style!css!sass' } ] }
    前面提到过,Webpack是经过文件的依赖关系进行加载分析的,因此当程序从主入口(js文件)进入后,在依赖的资源文件中发现有sass文件后,就会利用咱们配置的sass-loader去加载,而后用node-sass去解析编译成普通的css语法的样式文件,在而后就是利用style-loader将样式之内联样式的形式配置到html中(这里有一个问题,就是css-loader有什么用?我也没搞明白,可是不添加会报错,有知道的能够留言交流一下)。这样Webpack就完成了sass的预处理。

启动server

咱们都知道在前端开发中,ajax请求是须要启动一个server的。特别是在先后端分离思想中,前端开发再也不像之前同样过度依赖于后端开发,之前的那种前端测试ajax请求须要装个tomcat或者其它服务器来启动server的现象已经成为过去式,如今咱们可使用像Gulp这类前端自动构建工具启动一个本地server进行测试,不再收后端程序员钳制了(开个玩笑,和后端好好沟通才能让前端开发更方便)。那么,咱们来分别看一下Gulp和Webpack是怎样实现这个功能的。

Gulp启动server

在Gulp中想要启动一个本地serve,只须要如下几步:

  1. 在项目中经过npm安装一个gulp-webserver的模块
    $ npm install gulp-webserver -D
  2. 而后在Gulp的配置文件gulpfile.js中经过CommonJs规范引入gulp-webserver模块,并进行简单配置

    //1.引入 gulp-webserver 模块 var webserver = require('gulp-webserver'); //2.配置server task gulp.task('webserver',function(){ gulp.src('./') .pipe(webserver({ host:'localhost', port:80, //浏览器自动刷新 livereload:true, //显示文件目录 directoryListing:{ enable: true, path:'./' }, })); }); //3.配置默认task gulp.task('default',['webserver'],function(){ console.log('启动任务队列执行完毕'); })
  3. 在命令行中启动server

    $ gulp

    启动成功:


    gulp cli 启动成功
  4. 在浏览器地址栏中输入localhost打开页面验证。

通过以上这三步,咱们就在Gulp中启动了一个server了。在Gulp中启动本地服务有一个很方便的配置,就是livereload:true属性的设置,设置后浏览器会根据你项目中资源的变化自动刷新浏览器(若是你的chrome浏览器设置该属性后在你修改文件并保存时仍没有自动刷新,多是你的chrome浏览器不支持,能够chrome扩展程序中搜索并安装LiveReload插件),好比:
个人gulp测试目录结构:


gulp测试目录结构


index.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <script src="/src/scripts/app.js"></script> </body> </html>

我在app.js文件中输入如下内容,而后保存。

console.log('gulp-webserver livereload');

浏览器中控制台上会马上打印出一下信息:


gulp测试目录结构


说明浏览器自动刷新工程,这个小功能在咱们开发中屡试不爽。可是,这个功能是须要结合上一小节中的gulp.watch()实时监控文件变化,而后执行合并压缩和sass/less编译等操做后,浏览器再刷新时才能保证是咱们修改后的内容。因此,livereload:true属性只是监控到咱们修改文件后刷新浏览器从新请求文件,若是咱们不从新编译修改后的文件,浏览器获取到的仍是原文件,并不会展现变化。

Webpack启动server

在Webpack中也能够经过插件的形式安装一个webpack-dev-server来实现达到启动本地server的目的,具体步骤以下:

  1. 在项目中经过npm安装一个webpack-dev-server的模块
    $ npm install -g webpack-dev-server -D
  2. 而后在Webpack的配置文件webpack.config.js中进行简单配置
    module.exports = {
       devtool: 'eval-source-map', //webpack入口文件配置 entry: { app:__dirname + "/src/scripts/app.js", }, //webpack出口文件配置 output: { path: __dirname + "/prd/scripts/",//输出文件路径配置 filename: "bundle.js"//输出文件名配置 }, //本地server配置 devServer: { contentBase: __dirname,//本地服务器所加载的页面所在的目录 port:8089,//本地服务端口配置 colors: true,//终端中输出结果为彩色 historyApiFallback: true,//不跳转 inline: true//实时刷新 } }
  3. 在命令行中启动server
    $ webpack-dev-server
    而后你就会看见命令行输出内容不少,只要看看保证没有Error就说明成功了。
  4. 在浏览器地址栏中输入localhost:8089测试一下。

Webpack的启动本地服务也顺利实现了,是否是也想实现像Gulp同样浏览器自动刷新呀?那Webpack能不能实现呢?答案是确定的,Webpack官方提供了一个辅助开发工具,它能够自动监控项目下的文件,一旦有修改保存操做,开发服务器就会自动运行Webpack 打包命令,帮咱们自动将开发的代码从新打包。并且,若是须要的话,还能自动刷新浏览器,从新加载资源。理论上好像是这样,可是实现好像有很多限制,好比,HTML文件的自动刷新问题(html-webpack-plugin插件使用总是报错),当本地server启动在非output.path路径以外时则不能自动刷新等问题,等我再学习学习再说,或者有知道的能够留言讨论。

而这个辅助工具就是webpack-dev-server,它主要提供两个功能:一是为静态文件提供server服务,二是自动刷新和热替换(HMR)。因此想实现如Gulp同样的功能也是能够的,只须要在$ webpack-dev-server后面添加--inline --hot便可。须要注意的是--inline是自动刷新,同时在第二部中的devServer属性中有一个inline:true须要配置;而--hot是热替换(详细了解热替换了解webpack-dev-serverwebpack-dev-server)。

经过对比来看,好像Webpack的webpack-dev-server比Gulp的gulp-server功能要强一些。由于经过上面能够看出webpack-dev-server有两个大功能:一是为静态文件提供server服务,二是自动刷新(自动刷新其实须要两步:1.修改文件后,文件自动编译{包括合并压缩或者语法编译等},2.刷新浏览器请求最新编译后的文件)和热替换(HMR);而gulp-server虽然提供了启动本地server的能力和仅自动刷新浏览器的能力,缺乏一个文件自动编译的能力,这须要借助其余模块实现(上一小节已介绍,结合gulp.watch()实时监控文件变化,并编译)。

另外须要注意的是,实际开发中发现webpack-dev-server实现自动刷新的时候,并无执行自动编译,只是将修改的内容合并压缩等处理后发送给了浏览器,并形成了已经编译的现象,可是经过build/prd/scripts目录下的bundle.js(合并压缩后的输出文件)文件,能够发现内容并无编译(对于Webpack仍是不熟悉,好多问题等待解决)。

mock数据

在如今先后端分离的思想中,前端和后端耦合度愈来愈小,如今惟一须要先后端密切联系的就是借口的定义和数据格式的肯定。通常在项目开始前,前端和后端将项目中的接口和数据格式所有肯定下来(固然项目需求变动就须要临时确立这些共识了),而后前端就能够本身mock数据了。

Gulp实现mock数据

Gulp中对mock数据的实现使经过NodeJS内置的fs模块和url模块实现的,由于Gulp自己就是基于NodeJS的。还记得第一小节“模块化开发”中目录结构中的那个mock目录吗?那就是用来储存.json文件的mock数据目录。

  1. 配置Gulp的gulpfile.js文件
//1.引入 fs 和 url 模块 var fs = require('fs'); var url = require('url'); //2.从新配置一下上一小节的server gulp.task('webserver',function(){ gulp.src('./') .pipe(webserver({ host:'localhost', port:80, livereload:true, directoryListing:{ enable: true, path:'./' }, //mock数据配置 middleware:function(req,res,next){ var urlObj = url.parse(req.url,true); switch (urlObj.pathname) { case '/pro/getPro': res.setHeader('Content-Type','application/json;charaset=utf-8'); fs.readFile('./mock/list.json',function(err,data){ //上面list.json路径使用相对路径,绝对路径前台没法获取数据 res.end(data); }); return; case '/web/getUser': //.... return; } next(); } })); });

具体来讲,就是经过NodeJS拦截http请求,根据请求URL来模拟后端作出处理后返回不一样的数据。

Webpack实现mock数据

Webpack并无自带实现mock数据的功能,毕竟Webpack人家原本就是用来打包的,人家并非流程控制的,咱们能够和Gulp对比实现其余功能,是由于其余功能都是在打包过程当中实现的(启动server除外)。虽然Webpack没有自带mock数据的功能,可是咱们能够借助一些其余手段来实现,好比说json-server,它的实现原理就是,启动一个本地3000端口做为mock数据的端口,而后咱们在Webpack中配置一个代理,让全部请求代理到3000端口上去,就能够获取到数据了。
实现步骤:

  1. 在项目中经过npm安装一个json-server的模块
    $ npm install -g json-server
    能够将在任何一个目录下启动json-server,为了统一,咱们建议直接在项目根目录启动,将mock数据也放在项目根目录下。
  2. 启动json-server
    $ json-server
    json-server是一个很是强大的工具,感兴趣的能够自行google。
  3. 而后在Webpack的配置文件webpack.config.js中进行简单配置
    module.exports = {
       devtool: 'eval-source-map', entry: { app:__dirname + "/src/scripts/app.js", }, output: { path: __dirname + "/prd/scripts/", filename: "bundle.js" }, //本地server配置 devServer: { contentBase: __dirname, port:8089, colors: true, historyApiFallback: true, inline: true, //重点在这里 proxy:{ '/http://chping.website/*':{//为正则表达式,匹配以http://chping.website开头的url target: 'http://localhost:3000',//代理到本地3000端口 pathRewrite:{ '^/http://chping.website':''//将http://chping.website替换为空字符串 } } } } }
    说明:
    配置项'^/http://chping.website':''//将http://chping.website替换为空字符串的目的,举例说明:
    假设咱们项目中访问的是http://chping.website/userlist去获取用户列表,通过此配置项后,url为http://localhost:3000/userlist,不然为http://localhost:3000/http://chping.website/userlist/userlist
  4. 在命令行中从新启动server
    $ webpack-dev-server

版本控制

对于版本控制,咱们在开发过程当中,也是一个使用比较频繁的功能,特别是开发团队比较大的时候,这个功能就显得更加剧要了。那么Gulp和Webpack是具体怎样实现的呢?

Gulp实现版本控制

  1. 在项目中经过npm安装gulp-rev和gulp-rev-collector模块,前者用于生成文件的MD5码文件和按MD5码命名的资源文件,后者是利用MD5码,对文件名进行替换。
    $ npm install  gulp-rev gulp-rev-collector -D
  2. 而后在Gulp的配置文件gulpfile.js中进行简单配置
    //1.引入连个模块 var rev = require('gulp-rev'); var revCollector = require('gulp-rev-collector'); // 2.版本号控制 gulp.task('ver',function(){ gulp.src(cssFiles) .pipe(rev())//产生MD5码 .pipe(gulp.dest('./build/prd/styles/'))//重命名文件 .pipe(rev.manifest())//产生版本信息的json文件 .pipe(gulp.dest('./build/ver/styles/')); gulp.src(jsFiles) .pipe(rev()) .pipe(gulp.dest('./build/prd/scripts/')) .pipe(rev.manifest()) .pipe(gulp.dest('./build/ver/scripts/')); }) //动态修改html中对css和js文件的修改 gulp.task('html',function(){ gulp.src(['./build/ver/**/*','./build/*.html']) .pipe(revCollector()) .pipe(gulp.dest('./build/')); })

Gulp实现版本控制很方便,将这两个task加入gulp.watch()中,便可实现修改保存文件实时自动修改版本的功能。

Webpack实现版本控制

Webpack中须要版本控制的有css、js文件,不过Webpack的版本控制只实现了将css、js文件添加hash值方式命名的文件方式,修改引用路径中的文件名需手动实现。
不过实现确实很简单,只须要将webpack.config.js配置文件中的output.filename和plugins中的输出文件名称修改一下便可。

module.exports = { devtool: 'eval-source-map', entry: { app:__dirname + "/src/scripts/app.js", }, output: { path: __dirname + "/prd/scripts/", filename: "[name]-[hash].js"//修改输出文件名 }, plugins: [ new Et('./styles/[name]-[hash].css'),//修改输出文件名 ] }

这样就解决了。

组件控制

组件控制本来应该放在模块化小节或者先后小节,可是因为实在不知道该怎样比较,其实也没啥可比较的,就放在最后了。
Gulp和Webpack对各自组件的管理都是使用的npm进行的组件管理,想了解更多npm组件的管理的可自行百度,或者看看这篇文章入个门《npm介绍》

总结

经过以上八个方面的功能对比,Gulp和Webpack基本都能知足前端自动化构建工具的任务,可是仍是看出两个工具的侧重点是不通的,Gulp侧重整个过程的控制,Webpack在模块打包方面有特别出众。因此,Gulp + Webpack 组合使用可能更方便。

相关文章
相关标签/搜索