gulp與webpack的迷思

寫在前面: 這文章寫於15年底,後來16年才放到segmentfault上來,看到陸續仍是有瀏覽量甚至收藏,以避免形成誤導仍是在文章前頭稍稍提醒一下.
當時觀點放到今天不免有些打臉,就目前來講webpack已經徹底佔據主流位置,連我本身的項目都不多會在開發階段用glup了.但我依然以爲webpack與glup二者職能不一樣,例如把一些相似 測試任務, 上線部署之類的事交給gulp這類構建工具是很天然而然的事.webpack依然是打包工具,而打包,只是構建的其中一環而已.

你知道嗎?webpack出來統一天下了!

我已經不是第一次看到這相似的話語,爲數很多的人都以爲webpack是目前前端工程化完整性解決方案,打出了終於再也不用糾結使用grunt或是gulp了的旗號,只要使用webpack就足夠了javascript

而事實果然如此?css

首先看看webpack官網給出的解析html

webpack is a module bundler.

簡單來講,官方對webpack的定位是模塊打包器,相比於gulp或是grunt,webpack的競爭對手應該是browserify之流前端

就連webpack官方也給出了webpack with gulp的一些說明java

雖然webpack的確能夠代替gulp的一些功能
可是很是明顯webpack和gulp/grunt就不是一個職能的工具
因此說取代還言過其實(以前個人一個提問)react

那麼問題來了webpack

如何構建一個gulp與webpack相配合的前端工做流呢?

爲何是 gulp而不 grunt?
由於我用的是gulp - -!

要構建這樣一個工做流,首先要理清幾個問題git

  • 什麼工做應該交給gulp,什麼工做應該交給webpack
  • webpack貌似支持增量更新,gulp支持增量更新嗎?(這個是我以前一直很糾結的問題)
  • 如何實現livereload?

對於第一個問題

就如前面所說,webpack只是一個模塊打包器,因此,交予webpack處理的應該已經是通過各類lint檢查,各類編譯處理的代碼
而各類檢查,各類預處理就應該交給gulp之流了
最後壓縮代碼應該要交給webpack最後打包時再去執行es6

對於第二個問題

以前一直沒有注意這個問題
看看gulp的基本使用github

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**的設計模式,真的有讓你們 少寫不少代碼嗎?起碼我並不以爲有那麼一回事
我認爲,付出適當的代價,組合使用各類工具,使用合適的工做流,才能真正起到管理前端工程的做用

至於何爲適當,何爲合適,依然須要探索

相關文章
相關標籤/搜索