Grunt,Gulp 和 Webpack 的地位,我是这么认为的:
Grunt 是开创者 Grunt 的出现是前端构建工具从0到1的变革,是具有开创意义的。在它之前我们经常都是通过 bash 或者 make 调用 closure-compiler 之类的工具。前端并不存在一个统一的构建工具和标准,甚至我们自己写过一些简单的构建工具。Grunt的出现终结了这种混乱的局面,前端领域有了自己的构建工具,和大部分人都差不多采用的构建流程。
Grunt 虽然是开创者的地位,但是,他仅仅是把混乱的构建过程统一化了,用起来方便了,其实本质上没有变。本质上我们依然是把 CSS, JS, HTML,图片等 各自打包,一个JS模块依赖的 CSS 等外部资源依然没有任何语法上的声明,我们甚至需要在组件说明中强调这个组件依赖哪个CSS,依赖那几张图片。也就是说,模块依赖的问题依然没有解决。
另外 Grunt 是直接面向文件操作的,每一个任务都是输入一个文件,然后输出一个文件。这样导致如果一个文件需要经过多次处理,在中间每一步都会写文件,这些文件其实并没有必要写。这样就导致Grunt的效率比较低。 比如我编译JS的时候,可能需要先 CoffeeScript 编译一下,然后 Uglify 一下,那么很多时候 Coffee 编译的文件我并不需要,我只要 Uglify 之后的文件,而写文件是很耗时的。
Gulp 只是做了改良 Gulp 基于Stream 就明显比 Grunt要更高效,且更任务组合灵活。我可以读入一个文件,然后进行多个操作,最终直接输出我要的结果,不存在中间的临时文件。 然而 Gulp 只是一个量变,它依然没能解决模块依赖的问题。
Webpack 划时代的解决了模块依赖的问题 Webpack 的出现比较完美解决了前端模块依赖的问题,任何资源都是JS,任何资源都可以在JS中声明依赖。这是具有划时代意义的。甚至我是这样认为的,在webpack之前前端是没有真正的通用的模块化开发的(特定框架的不算)。 那么Webpack 是如何做到的呢?
所有模块都是JS模块 webpack 只支持JS模块,所有其他类型的模块,比如图片,css等,都需要通过对应的loader转成JS模块。所以在webpack中无论任何类型的资源,本质上都被当成JS模块处理。
- 对于CSS,我们可以把它转成一段JS,这个JS会把CSS插入到DOM中。
- 对于图片,我们可以把它进行base64转换变成一个字符串,或者进行文件拷贝然后导出它的URL
所有的loader都是一个管道
在webpack中,可以把一个loader看做是一个数据管道,进口是 一个字符串,然后经过加工,输出另一个字符串,多个loader可以像水管一样串联起来,很像java中的stream流。
loaders: [{
test: /\.scss$/,
loader: 'style!css!sass'
}]
这样的好处是:
- 单一职责,每个loader只负责处理一个单一的任务
- 我们可以通过组合不同的loader实现强大的功能。
另外 webpack 还带来了 Code Splitting,HMR, tree-shaking 等很多激动人心的特性。
一直以来对webpack都没有专门研究过,最近决定抽出时间对webpack进行一个深入的研究。当然不会讲webpack怎么用,配置文件怎么写,这些应该去webpack的官网查文档。大的方面来分,本系列主要包括这几个大主题:
常用的loader的实现原理 包括 babel-loader, css-loader, style-loader, url-loader, file-loader 等。通过源码来看他们的实现方式,并且尝试模仿他们自己动手写一个简单的loader。事实上前面说的这些loader 我都自己写了一个简单的版本出来。
webpack 源码分析 webpack 本身是一个插件式的框架,他的功能都是通过插件实现的。而webpack源码中的插件有几十个之多,这里我们先看看webpack插件架构的实现,然后挑一两个核心的插件来分析他的源码。
HMR实现原理 探究HMR 是如何实现的
tree-shaking tree-shaking的探讨,以及大家可能对tree-shaking工作原理的一些误解