## 1. [webpack](https://github.com/webpack/webpack) 是什么?
![](https://rails365.oss-cn-shenzhen.aliyuncs.com/uploads/photo/image/320/2017/5734645b60521d83d889a7716ff5a542.svg)
先来说一下 `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. 构建开发和生产环境-分离配置文件