webpack5 16 自定义plugin, react脚手架

tapable

听过阅读webpack的源码可以知道webpack有两个很重要的对象,一个是complier,一个是compilation,他们通过注入的方式来监听webpack的所有声明周期,插件的注入离不开hooks,而他们的hook也都是创建了tapable的各种hook实例而已。
Tapable是管理者需要的hook,这些hook可以被应用到我们的插件中。
webpack5 16 自定义plugin, react脚手架_第1张图片
这个tapable给我们提供的hook
如何使用呢?
cnpm install tapable -Dwebpack5 16 自定义plugin, react脚手架_第2张图片
最基本的使用asyncHook,在构造函数创建实例,然后通过tap注册事件,通过call触发事件。可以传入参数,tap第三个参数就是回调函数。
还有其他的类别,比如bail,当有返回值的时候,就不会执行后续事件的触发了。
webpack5 16 自定义plugin, react脚手架_第3张图片
loop,当返回值为true,会反复执行该事件,当返回值为undefined或者不返回内容,就退出事件
webpack5 16 自定义plugin, react脚手架_第4张图片
不断执行
Waterfall, 当返回值不为undefined时,会将这次返回的结果作为下次事件的第一个参数。
webpack5 16 自定义plugin, react脚手架_第5张图片
返回undefined或者不返回值时就继续向下执行。
上面都是以sync开头的hook,是同步
下面的是以async开头的hook,是异步
异步又有两种,一种是parallel 并行, 一种是series 串行
异步的监听与同步的稍有不同webpack5 16 自定义plugin, react脚手架_第6张图片webpack5 16 自定义plugin, react脚手架_第7张图片
串行执行,花费了4s.webpack5 16 自定义plugin, react脚手架_第8张图片
这是并行的,也就是花费的时间是2s多。

自定义plugin

将打包后的静态文件上传到服务器
一般插件是一个函数或者类,开发中我们一般是用类去定义一个插件,
webpack5 16 自定义plugin, react脚手架_第9张图片
webpack5 16 自定义plugin, react脚手架_第10张图片
这个插件是怎么注入到webpack的生命周期呢?
在webpack的CreateComplier中的第二步,plugin.apple(complier)就是注册所有的插件。所以自定义插件要实现一个apply方法,接受complier对象。
我们这个插件的目的是想将打包后的静态资源直接上传到服务器,所以得拿到相对应的hooks。
webpack5 16 自定义plugin, react脚手架_第11张图片

webpack5 16 自定义plugin, react脚手架_第12张图片
我们这时候在注册所有的插件的时候格外监听了一个函数。自定义的,然后在该hooks被调用,即callAscyn时,也就是静态资源文件打包成功后,这个函数会被调用。webpack5 16 自定义plugin, react脚手架_第13张图片
这时候自定义plugin已经生效了。
我们的插件也是可以传入数据的。如webpack5 16 自定义plugin, react脚手架_第14张图片
webpack5 16 自定义plugin, react脚手架_第15张图片
通过this.options就可以拿到配置的属性了。

小结 webpack中的complier和compilation对象的通过tapable这个库提供的很多hooks去监听webpack的声明周期。而我们的自定义插件也是通过hooks。在createComplier的第二步,webpack会注册所有的我们配置的plugin属性。这时候我们的自定义插件需要通过自定义的apply方法拿到Complier对象,再拿到这个对象的hooks-afteremit这个hooks,给这个hook额外注册一个事件,里面放着我们自己想要做的操作,当打包文件生成后,webpack就会执行afteremit.callAsync()去告诉所有监听者该事件已经触发了可以执行函数,这时候我们的自定义plugin里面的apply方法里面监听的事件就会触发,从而达到目的。简单的讲也是通过对hook做多一层的监听,然后等待hook被调用就可。

create-react-app react脚手架

webpack5 16 自定义plugin, react脚手架_第16张图片

react-script,通过这个将webpack的配置隐藏起来webpack5 16 自定义plugin, react脚手架_第17张图片
真正执行的是bin目录下的react-script.js文件
webpack5 16 自定义plugin, react脚手架_第18张图片
当我们执行yarn eject后
webpack5 16 自定义plugin, react脚手架_第19张图片
相当于直接执行script下的文件webpack5 16 自定义plugin, react脚手架_第20张图片
多了很多配置文件。
state.js
webpack5 16 自定义plugin, react脚手架_第21张图片
webpack5 16 自定义plugin, react脚手架_第22张图片

其中,这是start的核心,也就是加载webpack的配置文件 webpack5 16 自定义plugin, react脚手架_第23张图片
webpack5 16 自定义plugin, react脚手架_第24张图片公共的配置文件
webpack5 16 自定义plugin, react脚手架_第25张图片
导出一个函数webpack5 16 自定义plugin, react脚手架_第26张图片
返回一个对象。
看看webpack.confjg.js文件配置了什么。
webpack5 16 自定义plugin, react脚手架_第27张图片
第三则是判断是否需要热替换。(HMR)
webpack5 16 自定义plugin, react脚手架_第28张图片

webpack5 16 自定义plugin, react脚手架_第29张图片
这种写法是过滤掉为boolean为false的值。比如undefined,false,null等等。
webpack5 16 自定义plugin, react脚手架_第30张图片
判断sourceMap等等。这就是style-loader的处理
webpack5 16 自定义plugin, react脚手架_第31张图片
最后返回loaders,这个getStyleLoaders的箭头函数最终返回了一个loader。
接着是return的对象
webpack5 16 自定义plugin, react脚手架_第32张图片
webpack5 16 自定义plugin, react脚手架_第33张图片
webpack5 16 自定义plugin, react脚手架_第34张图片
webpack5 16 自定义plugin, react脚手架_第35张图片
接着是优化部分的,optimization
webpack5 16 自定义plugin, react脚手架_第36张图片
用了两个插件,都是我们用过的,还有solitChunks,runtimeChunk等的配置。
接着是resolve,解决对应路劲问题
webpack5 16 自定义plugin, react脚手架_第37张图片
resolveLoader,我们之前自定义loader时就使用过这个属性来配置对应的加载入口
webpack5 16 自定义plugin, react脚手架_第38张图片
接着就是module了
webpack5 16 自定义plugin, react脚手架_第39张图片
oneOf是啥呢?
oneOf表示一旦匹配到一个正确的规则,就不再匹配其他规则了。
webpack5 16 自定义plugin, react脚手架_第40张图片
只处理path.appSrc的文件,webpack5 16 自定义plugin, react脚手架_第41张图片
exclude则是排除掉。
webpack5 16 自定义plugin, react脚手架_第42张图片
css的设置,排除模块化的css,然后设置对应的sourcemap,还有ImportyLoaders,这个主要是遇到嵌套的css文件引入,可以回头使用像less-loader等的loader再做一次处理。sideEffects是tree-shaking的处理,表示这些文件都是有副作用的,不要删除。
接着就是plugin的设置了。
webpack5 16 自定义plugin, react脚手架_第43张图片

接着看下yarn build的文件

webpack5 16 自定义plugin, react脚手架_第44张图片

这个build拿到配置信息并且创建了complier对象,在运行run方法。

你可能感兴趣的:(webpack)