webpack
与 grunt
、gulp
的区别grunt、gulp
是基于任务运行的工具:它们会自动执行指定的任务,就像流水线,把资源放上去而后经过不一样插件进行加工,它们包含活跃的社区,丰富的插件,能方便的打造各类工做流。css
webpack
是基于模块化打包的工具:webpack
把一切都当作模块,当 webpack
处理程序时,会递归地构建一个依赖关系图,其中包含应用程序须要的每一个模块,而后将全部的模块打包成一个或者多个 bundle
。html
所以这是两类彻底不一样性质的工具,而 npm script
也能够打造任务流。前端
webpack
、rollup
、parcel
优劣webpack
适用于大型复杂的前端站点构建:webpack
有强大的 loader
和插件生态,打包后的文件实际上就是一个当即执行函数,这个当即执行函数接收一个参数(模块对象),键为各个模块的路径,值为模块内容。当即函数内部处理模块之间的引用、执行模块等,更适合文件依赖复杂的应用开发。vue
rollup
适用于基础库的打包,好比说vue
、d3
等。rollup
将各个模块打包进一个文件中,并经过 Tree-shaking
来删除无用的代码,能够最大程度上下降代码体积,可是 rollup
没有 webpack
那么多的代码分割、按需加载等功能,更加适合库的开发。webpack
parcel
适用于简单的实验性项目:能够知足低门槛的快速看到效果,可是生态差、报错信息不够全面都是问题,除了一些实验性项目不建议使用。web
loader
file-loader
把文件输出到一个文件夹中,在代码中经过相对 URL 引用输入的文件url_loader
和 file-loader 相似,能在文件很小的状况下以 base64 的方式将文件内容注入到代码中source-map-loader
加载额外的 Source Map 文件,方便断点调试image-loader
加载并压缩图片文件babel-loader
将 ES6 转换为 ES5css-loader
加载 css,支持模块化、压缩、文件导入等特性style-loader
把 css 代码注入到 JavaScript 中,经过 DOM 操做去加载 csseslint-loader
经过 ESLint 检查 JavaScript 代码html-minify-loader
压缩HTMLloader
特性package.json
的 main 来将一个 npm 模块导出为 loader,还能够在 module.rules
中使用 loader 字段直接引用一个模块plugin
define-plugin
定义环境变量html-webpack-plugin
简化 html 文件建立uglifyjs-webpack-plugin
经过 UglifyES 压缩 ES6 代码webpack-parallel-uglify-plugin
多核压缩,提升压缩速度webpack-bundle-analyzer
可视化 webpack 输出文件的体积mini-css-extract-plugin
CSS 提取到单独的文件中,支持按需加载clean-webpack-plugin
在每次构建前清理 /dist 文件夹loader
和 plugin
的不一样loader 为加载器,webpack 将一切文件视为模块,可是 webpack 原生只能解析 js 和 json 文件,若是想将其余文件也打包的话,就会用到 loader,所以,loader 的做用是让 webpack 能够加载和解析非 JavaScript 文件。npm
plugin 为插件。能够扩展 webpack 的功能,让 webpack 更灵活。在 webpack 的运行周期中会广播出许多事件,plugin 能够监听这些事件,在合适的时机经过 webpack 提供的 API 改变输出结果。json
loader 在 module.rules 中配置,即做为模块的解析规则存在。类型为数组,每一项都是一个 object,里面描述了对于什么类型的文件是用什么加载和使用的参数。gulp
plugin 在 plugins 中单独配置。类型为数组,每一项是一个 plugin 的实例,参数都是经过构造函数传入。数组
bundle
、chunk
、module
bundle
由 webpack
打包出来的文件
chunk
代码块,一个 chunk
由多个模块组合而成,用于代码的合并和分割
module
开发中的单个模块,webpack
中一切皆模块,一个模块对应一个文件
webpack
的构建流程webpack 的运行流程是一个串行的过程,从启动到结束会一次执行如下流程:
在以上过程当中,webpack 会在特定的时间点广播出特定的时间,插件在监听到事件后,会执行特定的逻辑,而且插件能够调用 webpack 提供的 API 改变 webpack 的运行结果。
loader
和 plugin
loader
把读到的源文件内容转义成新的文件内容,而且每一个 loader
经过链式操做,将源文件转换成想要的样子。
编写 loader
的时候要遵循单一原则,每个 loader
只作一种转义工做,loader
拿到的是源文件内容(source
),处理后能够经过返回值的方式将处理后的内容输出,也能够调用 this.callback()
方法将内容返回给 webpack
。还能够经过 this.async()
生成一个 callback
函数,再用这个 callback
将处理后的内容输出出去。此外 webpack 还为开发者准备了开发 loader
的工具函数集 —— loader-utils
plugin
监听 webpack 运行中广播出的事件,在合适的时机经过 webpack 提供的 API 改变输出结果。
webpack
的热更新是如何作到的热更新又称做热替换(Hot Module Replacement),缩写为 HMR。这个机制能够作到不用刷新浏览器而将新变动的模块替换掉旧的模块。
热更新在 server
端和 client
端都作了处理
webpack
的 watch
模式下,文件系统中的某个文件发生改变,webpack
监听到文件变化,根据配置文件对模块从新编译打包,并将打包后的代码经过简单的 JavaScript
对象保存在内存中。webpack-dev-server
和 webpack
之间的接口交互,这一步,主要是 dev-server
的中间件 webpack-dev-middleware
和 webpack
之间的交互,webpack-dev-middleware
调用 webpack
暴露的 API 对代码变化进行监控,而且告诉 webpack
将代码打包到内存中。webpack-dev-server
对文件变化的监控,并非监控代码变化从新打包。当在配置文件中配置了 devServer.watchContentBase
为 true
的时候,server
会监听这些配置文件夹中静态文件的变化,变化后会通知浏览器端对应用进行 live reload
,这里是浏览器刷新。wecpack-dev-server
代码的工做,主要经过 sockjs
(webpack-dev-server
的依赖)在浏览器端和服务器端创建一个 websocket
的长链接,将 webpack
编译打包的各个阶段的状态信息告知浏览器端,同时也包括第3步中 server
监听静态文件变化的信息。浏览器端根据这些 socket
消息进行不一样的操做,服务端传递的主要信息仍是新模块的 hash
值,后面的步骤根据这一 hash
值来进行模块热替换。webpack-dev-server/client
端并不可以请求更新代码,也不会执行热更新模块操做,这些工做依旧会交回给 webpack
,webpack/hot/dev-server
的工做是根据 webpack-dev-server/client
传给它的信息以及 dev-server
的配置决定是刷新浏览器仍是进行模块热更新。若仅仅是刷新浏览器,就没有后续的操做了。HotModuleReplacement.runtime
是客户端 HMR
的中枢,接收上一步传给它的新模块的 hash
值,经过 JsonpMainTemplate.runtime
向 server
端发送 Ajax
请求,服务端返回一个 json
,该 json
包含了全部要更新的模块的 hash
值,获取到更新列表后,该模块再次经过 jsonp
请求获取到最新的模块代码。HotModulePlugin
会对新旧模块进行对比,决定是否更新模块,再决定更新模块后,检查模块之间的依赖关系,更新模块的同时更新模块间的依赖引用。HMR
失败后,回退到 live reload
操做,也就是进行浏览器刷新来获取最新打包代码。webpack
优化前端性能UglifyJsPlugin
和 ParallelUglifyPlugin
来压缩 JS 文件,利用 cssnano
来压缩 css 代码。webpack
对于 output
参数和各个 loader
的 publicPath
参数来修改资源路径。Tree Shaking
:将代码中永远不会走到的片断删除掉,能够在启动 webpack
时追加参数 --optimize-minimize
来实现。Code Splitting
:将代码按照路由维度或者组件分块,能够作到按需加载,同时能够充分利用浏览器缓存。SplitChunksPlugin
插件来进行公共模块抽取,利用浏览器缓存能够长期缓存这些无需频繁变更的公共代码。webpack
的打包速度happypack
:利用进程并行编译 loader
,利用缓存来使得 rebuild
更快,相似的替代者:thread-loader
。webpack
打包,减小打包时间。dll
:采用 webpack
的 DllPlugin
和 DllReferencePlugin
引入 dll
,让一些基本不会改动的代码先打包成静态资源,避免反复编译浪费时间。webpack.cache
、babel-loader.cacheDirectory
、HappyPack.cache
均可以利用缓存提升 rebuild
的时间。babel-loader
,若文件仅存在于 src
中可使用:include: path.resolve(__dirname, src)
webpack
的构建速度CommonsChunkPlugin
来提取公共代码external
配置来提取经常使用库DllPlugin
和 DllReferencePlugin
预编译资源模块,经过 DllPlugin
来对哪些引用可是绝对不会修改的 npm
包来进行预编译,再经过 DllReferencePlugin
将预编译的模块加再加载进来HappyPack
实现多线程加速编译webpack-uglify-parallel
来提高 uglifyPlugin
的压缩速度Tree-shaking
和 Scope Hoisting
来剔除多余代码