## 1. [webpack](https://github.com/webpack/webpack) 是什么?

先來說一下 `webpack` 是什么。
`webpack` 的官方對它是這樣定義的:
> `webpack` is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.
中文的大概意思是說:
> `webpack` 可以看做是模塊打包機:它做的事情是,分析你的項目結構,找到 `JavaScript` 模塊以及其它的一些瀏覽器不能直接運行的拓展語言(`Scss`,`TypeScript` 等),并將其轉換和打包為合適的格式供瀏覽器使用。
用大白話可以這樣說:
> `webpack`是一個前端模塊化方案,更側重模塊打包,我們可以把開發中的所有資源(圖片、js 文件、css 文件等)都看成模塊,通過 `loader`(加載器)和 `plugins`(插件)對資源進行處理,打包成符合生產環境部署的前端資源。
如果這樣還不明白的話,我們來說下前因后果。
在當今的社會,作為 web 開發,會越來越意識到前端的重要性,隨著 `HTML5`、 `CSS3`、 `ES6` 各種技術的發展,前端的開發越來越寵大。甚至有些應用就是單頁面應用(SPA),純 `JavaScript` 開發,`JavaScript` 文件的管理也是一個問題。`JavaScript` 模塊化編程,已經成為一個迫切的需求,這就出現了 `JavaScript` 的模塊解決方案,以前是用 `requirejs` 或 `seajs`,而現在則是用 `webpack`。
舉個例子,很多人開發了各種優秀的 `JavaScript` 模塊或組件,我們不想重復發明輪子,而是想直接利用別人的模塊,就是類似 `require` 或 `include` 這樣的機制,把別人的模塊引入進來,但是 `JavaScript` 又沒有 `類`或`包` 這樣的概念,那應該如何做呢?
如何去引入別人的模塊?引入之后保證各種依賴關系不出錯?這就是 `webpack` 要解決的問題。
模塊化的概念我們理解了,那如何理解 `打包` 這個詞呢?
其實,模塊化的問題解決之后,`webpack` 就能把各種資源模塊打包合并成一個文件輸出給瀏覽器。在打包的過程中還能對這些資源進行處理,比如壓縮減少體積,把 `sass` 編譯成 `css`, `coffee` 編譯成 `js`。所以它在某些程度上,跟 `grunt/gulp` 的功能有些相同。至于與 `grunt/gulp` 的不同之處,我們下面會講到。
## 2. 與 `grunt/gulp` 的區別
`grunt/gulp` 的定義是 `Task Runner`。它有點像 `ruby` 的 `Rake`或 `Thor`,如果你不懂 `ruby`,那 `c/cpp`語言的 `make`,這應該總知道吧。它是一種寫任務的工具,只是 `grunt/gulp` 是用 `JavaScript` 來寫 task 而已。
`grunt/gulp` 強調的是前端開發的工作流程,我們可以通過配置一系列的 task,定義 task 處理的事務(例如文件壓縮合并、雪碧圖、啟動 server、版本控制等),然后定義執行順序,來讓 `grunt/gulp` 執行這些 task,從而構建項目的整個前端開發流程。
``` javascript
const gulp = require('gulp');
const babel = require('gulp-babel');
// gulp.src 會指定源文件,然后通過 pipe 函數把內容傳給下個處理方法,最后 gulp.dest 是輸出處理后的文件內容。
gulp.task('default', () =>
gulp.src('src/app.js')
.pipe(babel({
presets: ['es2015']
}))
.pipe(gulp.dest('dist'))
);
```
打個比方,如果你的工程模塊依賴很簡單,不需要把 js 或各種資源打包,只需要簡單的合并、壓縮,那就不需要 webpack。grunt/gulp 就夠用了。反過來,如果你的工程龐大,頁面中使用了很多庫(SPA很容易出現這種情況),那就可以選擇使用 `webpack`,因為這樣既能做到模塊化管理,也能做到 `grunt/gulp` 的一些功能,比如壓縮,轉化 `coffeescript` 為 `js` 等。
> `gulp` 也能和 `webpack` 結合起來用,`gulp` 里面有個 [webpack-stream](https://github.com/shama/webpack-stream) 插件。就是讓 `webpack` 專門去做 module dependency 的事情, 生成一個 `bundle.js` 文件,然后再用 `gulp` 去做一些其他雜七雜八 minify, uglify 的事情。 后來人們發現 `webpack` 有個 `plugins` 的選項, 可以用來進一步處理經過 `loader` 生成的 `bundle.js`,于是有人寫了對應的插件, 所以 minify/uglify, 生成 hash 的工作也可以轉移到 `webpack` 本身了,擠掉了 `gulp` 這部分的市場份額。 再后來大家有發現 `npm/package.json` 里面的 scripts 原來好好用啊,調用任務的時候就直接寫一個簡單的命令,因為 `gulp` 也不就是各種插件命令的組合呀,大部分情況下越來越不需要 `gulp/grunt` 之類的了。 所以你現在看到的很多新項目都是`package.json` 里面 scripts 寫了一堆,外部只需要一個 `webpack` 就夠了。(摘自網絡 https://segmentfault.com/q/1010000008058766)
最后總結一下:
雖然都是前端自動化構建工具,但看他們的定位就知道不是對等的。
`grunt/gulp` 嚴格上講,模塊化不是他強調的東西,他旨在規范前端開發流程。
`webpack` 更是明顯強調模塊化開發,而那些文件壓縮合并、預處理等功能,不過是他附帶的功能。
## 3. 跟 Browserify 相比
`webpack` 與其和 `grunt/gulp` 相比較,還不如跟 `Browserify` 比較,因為它們兩者更相近,不過好像 `Browserify` 應該被 `webpack` 代替了吧,我對 `Browserify` 了解也不多,在此就不細說了。
## 4. 優勢
1. `webpack` 不僅僅能處理 js, 也能處理 css, 也能處理 html,甚至是圖片等各種前端資源。
2. 它開發便捷,僅僅使用一個配置文件,就能替代部分 `grunt/gulp` 的工作,比如打包、壓縮混淆、圖片轉 base64等。
3. 擴展性強,插件機制完善。
## 5. 為什么要學習 `webpack`
現在最流行的 `react`、`vue`、`angular` 等技術,你要學習和使用它們,難免會碰到 `webpack`,因為一般都會用 `webpack` 來構建前端的開發環境,這樣,我們還有什么理由不學習呢?
- 0. 開始
- 1. 介紹
- 2. 安裝
- 3. 實現 hello world
- 4. webpack 的配置文件 webpack.config.js
- 5. 使用第一個 webpack 插件 html-webpack-plugin
- 6. 使用 loader 處理 CSS 和 Sass
- 7. 初識 webpack-dev-server
- 8. 用 webpack 和 babel 配置 react 開發環境
- 9. 用 clean-webpack-plugin 來清除文件
- 10. 配置多個 HTML 文件
- 11. 如何使用 pug (jade) 作為 HTML 的模板
- 12. 如何使用模塊熱替換 HMR 來處理 CSS
- 13. 生產環境 vs 開發環境
- 14. 如何打包圖片
- 15. 加載和打包 Twitter Bootstrap 框架
- 16. 使用 ProvidePlugin 插件來處理像 jQuery 這樣的第三方包
- 17. 輕松通過兩個實例來理解 devtool: 'source-map' 是什么意思
- 18. 構建開發和生產環境-分離配置文件