gulp与webpack的迷思

写在前面: 这文章写于15年末,后来16年才放到segmentfault上来,看到陆续还是有浏览量甚至收藏,以免造成误导还是在文章前头稍稍提醒一下.
当时观点放到今天难免有些打脸,就目前来说webpack已经完全占据主流位置,连我自己的项目都很少会在开发阶段用glup了.但我依然觉得webpack与glup两者职能不同,例如把一些类似测试任务,上线部署之类的事交给gulp这类构建工具是很自然而然的事.webpack依然是打包工具,而打包,只是构建的其中一环而已.

你知道吗?webpack出来统一天下了!

我已经不是第一次看到这类似的话语,为数不少的人都觉得webpack是目前前端工程化完整性解决方案,打出了终于不再用纠结使用grunt或是gulp了的旗号,只要使用webpack就足够了

而事实果真如此?

首先看看webpack官网给出的解析

webpack is a module bundler.

简单来说,官方对webpack的定位是模块打包器,相比于gulp或是grunt,webpack的竞争对手应该是browserify之流

就连webpack官方也给出了webpack with gulp的一些说明

虽然webpack的确可以代替gulp的一些功能
但是非常明显webpack和gulp/grunt就不是一个职能的工具
所以说取代还言过其实(之前我的一个提问)

那么问题来了

如何构建一个gulp与webpack相配合的前端工作流呢?

为什么是gulp而不grunt?
因为我用的是gulp - -!

要构建这样一个工作流,首先要理清几个问题

  • 什么工作应该交给gulp,什么工作应该交给webpack
  • webpack貌似支持增量更新,gulp支持增量更新吗?(这个是我之前一直很纠结的问题)
  • 如何实现livereload?

对于第一个问题

就如前面所说,webpack只是一个模块打包器,所以,交予webpack处理的应该已是经过各种lint检查,各种编译处理的代码
而各种检查,各种预处理就应该交给gulp之流了
最后压缩代码应该要交给webpack最后打包时再去执行

对于第二个问题

之前一直没有注意这个问题
看看gulp的基本使用

gulp.src('client/templates/*.jade')
  .pipe(jade())
  .pipe(minify())
  .pipe(gulp.dest('build/minified_templates'));  

对于开发中gulp会使用watcher实时检查文件是否更新,检查到有更新则马上跑相应的构建任务,但是有上面的代码可以看出,gulp每次都只能通过通配符匹配大量的文件,而不能就单单获取修改过的文件,这种情况在大型项目中每次构建都会花不少时间,更别论要在构建任务之后再加一个webpack的打包任务

不过所幸上网找到一个gulp-changed的插件,实在棒!

对于第三个问题

之前开发时live reload都是交给gulp的,而现在gulp的构建任务并不是在任务链的最后端,由gulp来实现显然不再合适

实践实践

基于上面的思考,我做了个尝试项目

做些简单的说明,上面的项目只有简单的几个构建任务

对于js

gulp.task('js', function() {
  return gulp.src('src/**/*.js')
        .pipe($.changed('build'))
        // .pipe($.babel({
        //   presets: ['es2015', 'react']
        // }))
        .pipe($.eslint({config: 'eslint.config.json'}))
        .pipe($.eslint.format())
        .pipe(gulp.dest('build'));
});

只简单的用eslint检测一下语法而已,而注释的部分,是使用babel把es6的代码转化成es5的代码,但是这部分应该是由webpack在最后打包阶段处理,所以去掉了

对于css

gulp.task('css', function() {
  return sass('src/**/*.scss')
        .pipe($.changed('build'))
        .on('error', sass.logError)
        .pipe($.replace('@@FILEURL', fileUrl))
        .pipe(gulp.dest('build'));
});

就是把scss转化成css,并替换掉css文件中的占位符(可以根据需求加上自动合并雪碧图或者postcss处理等等)
这里要说明一下在这个示例项目中其实并没有实际编写任何css或scss,因为项目中的todo应用实际是从redux todo直接拷贝的 = =!

对于html

gulp.task('html', function() {
  return gulp.src('src/**/*.html')
        .pipe($.changed('build'))
        .pipe($.replace('@@FILEURL'), fileUrl)
        .pipe(gulp.dest('build'));
});

就没什么好说的,就是做了一下占位符替换而已
如果是使用其他模板引擎就可以在这里进行编译

而live reload应该怎么做呢?

参考了一下react-transform-boilerplateredux todo(其实还是直接拷贝的= =)


gulp.task('default', ['clean', 'js', 'css', 'html', 'watch'], function() {
  var app = require('./devServer');
  var port = 3000;
  app.listen(port, function(error) {
    if (error) {
      console.error(error)
    } else {
      console.info("==> ?  Listening on port %s. Open up http://localhost:%s/ in your browser.", port, port)
    }
  });
});

就是再把所有任务跑一遍后启动实现live reload的devServer
修改文件时,gulp就会从src->build进行构建,而webpack则是检测着build文件夹是否有更新来进行增量编译,同时实现live reload

至此,已经把脑中想法基本实现了出来(其实并没有,bug多多的说)

写在最后

再来说说实践过后的想法

webpack果真是业界杀鸡用牛刀的最佳代言人

好吧,可能是我接触webpack不久
在如此小的应用上,使用webpack真是一点都体会不出它的好处
(唯一一点可能就是es6的import语法而已,不过要使用import还是react或redux等等库的坑)
在大型项目使用可有成功案例,希望大家不吝指教一下^ ^~
另外一点,我还看过几篇比较gulp和webpack的博文(国内外都有)
大意其实都差不多,就是说,如果用gulp,你要写多很多代码,你将会有非常多的开发依赖balabala....
而用webpack,你就可以通过少量的代码解决这些问题等等等等的,
且不论代码多少的问题,这点我并没有实践过
但是再一次表明我的看法

webpack和gulp/grunt就不是一个职能的工具,谈何取代?
至于代码多少的问题
有没有想过,代码少就真的一定吗?
我认为,gulp/grunt或是browserify/webpack等等工具的面世,其实都是为了解决前端的工程化问题
工程化问题面前,难道追求的真的是write less, do more吗?
举个例子,各种MV**的设计模式,真的有让大家少写很多代码吗?起码我并不觉得有那么一回事
我认为,付出适当的代价,组合使用各种工具,使用合适的工作流,才能真正起到管理前端工程的作用

至于何为适当,何为合适,依然需要探索


尘世间一名迷途小码农的思考
前端,nodejs为主,及其他任何我感兴趣的事

不折不扣的乐天派

2.2k 声望
25 粉丝
0 条评论
推荐阅读
前后端分离之更好的mock你的后端api
注意! 广告警告! 广告警告! 广告警告! 在一个web应用的开发周期中, 一般前端与后端都是并行开发的, 各自完成自己的开发工作后进行联调, 联调通过再进行提测/发布. 开发过程中, 前端都会以后端提供的 api 文档作为...

funkyLover30阅读 5k评论 1

从零搭建 Node.js 企业级 Web 服务器(零):静态服务
过去 5 年,我前后在菜鸟网络和蚂蚁金服做开发工作,一方面支撑业务团队开发各类业务系统,另一方面在自己的技术团队做基础技术建设。期间借着 Node.js 的锋芒做了不少 Web 系统,有的至今生气蓬勃、有的早已夭折...

乌柏木150阅读 12.3k评论 10

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木66阅读 6.2k评论 16

从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木44阅读 7.4k评论 6

从零搭建 Node.js 企业级 Web 服务器(二):校验
校验就是对输入条件的约束,避免无效的输入引起异常。Web 系统的用户输入主要为编辑与提交各类表单,一方面校验要做在编辑表单字段与提交的时候,另一方面接收表单的接口也要做足校验行为,通过前后端共同控制输...

乌柏木33阅读 6.2k评论 9

从零搭建 Node.js 企业级 Web 服务器(五):数据库访问
回顾 从零搭建 Node.js 企业级 Web 服务器(一):接口与分层,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,控制层与服务层实现了业务处理过程,模型层定义了业务实体并以 对象-关系...

乌柏木34阅读 4.6k评论 9

从零搭建 Node.js 企业级 Web 服务器(十三):断点调试与性能分析
Node.js 官方提供了断点调试机制,出于安全性考虑默认为关闭状态,可以通过 node 参数 --inspect 或 --inspect-brk 开启,配合 IDE 能够非常方便地调试代码,本章就上一章已完成的项目 licg9999/nodejs-server-ex...

乌柏木31阅读 3.9k评论 9

不折不扣的乐天派

2.2k 声望
25 粉丝
宣传栏