entry:入口。webpack是基于模块的,使用webpack首先需要指定模块解析入口(entry),webpack从入口开始根据模块间依赖关系递归解析和处理所有资源文件。
output:输出。源代码经过webpack处理之后的最终产物。
loader:模块转换器。本质就是一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。 因为 Webpack 只认识 JavaScript,所以 Loader 就成了翻译官,对其他类型的资源进行转译的预处理工作。
plugin:扩展插件。基于事件流框架 Tapable,插件可以扩展 Webpack 的功能,在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
module:模块。除了js范畴内的es module、commonJs、AMD等,css @import、url(...)、图片、字体等在webpack中都被视为模块。
初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数;
初始化编译:用上一步得到的参数初始化 Compiler 对象,注册插件并传入 Compiler 实例(挂载了众多webpack事件api供插件调用);
AST & 依赖图:从入口文件(entry)出发,调用AST引擎(acorn)生成抽象语法树AST,根据AST构建模块的所有依赖;
递归编译模块:调用所有配置的 Loader 对模块进行编译;
输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;
输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统;
在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到相关事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果
构建流程核心概念:
Tapable:一个基于发布订阅的事件流工具类,Compiler 和 Compilation 对象都继承于 Tapable
Compiler:webpack编译贯穿始终的核心对象,在编译初始化阶段被创建的全局单例,包含完整配置信息、loaders、plugins以及各种工具方法
Compilation:代表一次 webpack 构建和生成编译资源的的过程,在watch模式下每一次文件变更触发的重新编译都会生成新的 Compilation 对象,包含了当前编译的模块 module, 编译生成的资源,变化的文件, 依赖的状态等
(1)通常从优化构建速度和使用体验
1.缩小文件的搜索范围(loader配置inculd/exclude. module.noparose)
2.自动刷新
3.热更新(网页不刷新,状态不会丢失module.hot)
4. DllPlugin(对依赖的第三方库打包成动态链接库)
生产环境
1.优化bable-loader (开启缓存)
2.IgnorePlugin
3.noParse
4.happlepack(多线程打包)
5. ParallelUglifyPlugin
(2)优化输出质量
(减少用户能感知到的加载时间,也就是首屏加载时间)
1.区分环境
2.压缩代码 (js css代码)
3.出去没有用到的代码
4.提取公共代码(多线程打包)
5.分割代码按需加载(多线程打包)
6.CDN加速
自动刷新
让webpack开启文件监听模式只需要设置watch:true
文件监听原理
1.文件监听原理就是定时获取这个文件最后的编辑时间,每次都存下最新的最后编辑时间,如果发现当前获取和最后一次保存的编辑时间不一致,认为文件发生了变化。
自动刷新原理
1.借助浏览器拓展去通过浏览器提供的接口刷新
热更新
1.实时阅览
2.不刷新浏览器,可以以保存当前网页的运行状态
原理
1.在项目中注入一个代理客户端来连接Devserve和项目
2.Devserve在每次修改文件后,会生成一个替换老模板的补丁文件hot-update.js结尾,同事浏览器开发者工具也能看到请求的这个补丁包
3.但在编辑main.js这个文件的时候会发现整个网页都刷新了,原因是子模块发生更新的时候,更新事件会一层层向上传递,到最外层没有文件接受它,则会刷新网页
4.css文件没有地方接受,但在修改所有css文件都会触发热更新,原因是在于style-loader会注入接受的css的代码
DllPlugin
对于依赖的第三方库,比如vue,vuex等这些不会修改的依赖,我们可以让他和我们自己编写的代码分开打包,这个样做的好处是每次更改我本地的代码的文件的时候,webpack只需要打包我项目本身的文件代码,而不会去编译第三方库,那么第三方库在第一次打包的时候只打包一次,以后我们只要不升级第三方包的时候,那么webpack就不会对这些库进行打包,这样可以快速的提高打包的速度
1.将项目依赖的基础模块抽离出来,打包到一个个单独的动态链接库
2.当需要导入的模块存在于某个动态链接库中,这个模块不能被打包,直接在动态链接库中获取
3.项目依赖的所有动态链接库都要被加载
bable-loader
1.作用是识别es6+的语法
2.通过js词法解析器解析,得到AST,然后进行遍历通过EStree规范生成新的AST,然后通过生成器转换ES5代码
happlepack(多进程构建,减少总构建时间)
在webpack和loader之间多了一层,webpack到了需要编辑某类型的资源模块之后,将该资源任务处理交给了happePack,由他在内部线程池中进行任务调度,分配一个线程调用处理改类型资源的loader来处理这个资源
如果js和css文件的化,直接再module,rules,use['happyPack/loader?id=css']也可以在 plugins里配置,new HappyPack({id:css}),id标识文件类型默认进程是3个,threads可以设置