Webpack漫谈

tech2024-03-30  77

1. 核心概念

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中都被视为模块。

2. 打包流程

初始化参数:从配置文件和 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, 编译生成的资源,变化的文件, 依赖的状态等

webpack打包优化方向

(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可以设置

 

 

 

 

 

 

 

 

 

最新回复(0)