Webpack Plugins System Tapable Plugin System
Transcript from the "Tapable Plugin System" Lesson
>> Sean Larkin: So, we're gonna actually get kind of in depth. Considerably in depth, one of the things that I think is really important and unlocks the ability for you to do anything you've ever imagined with webpack is actually, right custom plugins. And so, all of webpack is made of plugins, right?
[00:00:21] And so, to know that, it really helps to understand what the architecture is and what you can plug into, right? So, what is Tapable? Has anybody even heard of Tapable? Maybe you might have heard about it today, just as I was talking about it at lunch. So, it used to be originally, a 200 line library.
[00:00:45] Now we just rewrote it from the ground up for webpack 4. But it is the entire, it's the entire backbone of webpack. Like it is the plugin system, it is how we write plugins, it's how plugins are registered. It's how webpack adds any functionality that you could ever think.
[00:01:06] Cuz our whole application is made or the library code is made of plugins. So originally, in webpack 3 and before, so before webpack 4, this was how the API worked. In this code example, you can see that we have a compiler instance and actually, it may even just be more valuable for me to pull this up in the source code itself, which I have available.
[00:01:33] So, let me do that. It should just take a second. [COUGH] So, webpack, lib, compiler, okay
>> Sean Larkin: All right, so we only have a very few, so everything is very object-oriented in webpack, cuz the original author is a C# developer by trade. So [LAUGH] but,
>> Sean Larkin: We use Tapable in our library, or in our source code, which you're seeing right now, to extend and add these methods and behaviors into like specific classes.
[00:02:22] We call these Tapable instances, right? So it extends Tapable, the compiler. Now, we also as part of tapable, we define hooks that are instantly available when this instant is. Well, when it's instantiated or inside the constructor. So you can see here, early before, when I showed that, they were just added on the prototype chain and there are arbitrary string events, right?
[00:02:54] So this is the major change between webpack 3 and 4. In 3, we would add these methods called apply plugins and we'd have like apply plugins async, apply plugins parallel. Apply plugins sync, like there's all these different ways of executing plugins that are registered. And their events. And then their events themselves, like EventEmitter were just strings.
[00:03:15] And so it wasn't a very good developer experience. Like as a plugin author, you would have to literally search through the code base and feel like, apply plugins and then try and find event streams, right? Cuz we didn't have it completely documented. So, one of the greatest upgrades we did for Tapable is that we added, we made sure that hooks are static, right?
[00:03:37] So, now at anytime if you're writing or if you're testing this or you add a debugger. You can instantly just type this .hooks or compiler.hooks and you can see everything that you can plug into. Or even adding annotations so that we can make reference documentation. So there are all different events which are different parts of the webpack lifecycle, right?
[00:04:01] And so, ic something wants to hook into it. So in version three, we would have this, let's just say an example plugin we have here. So in this case, remember when I talked about the only rules for a plugin in its anatomy is that it has to have, it's an object or an instance.
[00:04:19] In this case, we can write a class with ES6 support. And all it has to have is an apply method, right? And when webpack calls apply plugins whatever, it goes and finds the things registered to that event. And webpack passes that compiler instance, right. So this was in V3 how the syntax would look.
[00:04:41] You would basically write compiler,plugin. It's kinda like eventEmitter.on. It's almost identical. And whatever event you're trying to listen to, right? And then a callback would occur when that event actually fires, and you have access to that data and get to do whatever custom behavior that you would like to.
[00:05:01] An example with V4, it almost looks identical, so if, and I'll show you that once we talk about building a custom plugin. But, I'll just go to a very simple one. So, the way that you can add like, even the way we that we take the entry point and we set it to start building the graph, is literally a plugin called the entry option plugin.
[00:05:25] Right, and what this does is we, as you can see here here's an apply method. We grab the compiler and then we say compiler.hooks and then the name of the hook. So it's not an event string anymore. We actually have a hook that we can see and get influence on.
[00:05:45] And then first, so we say.tap. So that's like equivalent of .plugin. So .tap and then the first parameter is metadata or for analytics, or not analytics but like diagnostics. So, if we need to know what is hooking into this, we can see that it's the entry option plugin.
[00:06:08] So, typically you just provide the plugin name. It's optional, you could have whatever you wanted here, but this allows us to identify like, this code happened or this hook was taking really long time, or it's the entry option plugin's fault. But in the same way, we get a callback which has the data that's passed into it.
[00:06:27] And in this case what we're doing is we're saying well there's three different data types that ca be set for the entry property. It can be an object, a string literal, or an array, right? And so all this plugin is doing is just saying like those are the string?
[00:06:39] Okay, use the single entry plugin, if not use multi, if not use dynamic. And so this is how we compose and create small like, we isolate behavior individual plugins, right? So now we can just apply this plugin. And in this case we're actually adding that entry point as the dependency to start building the graph, right?
[00:07:04] So that in a nutshell is kind of like how the new plugin system APIs work. So going back, [COUGH]
>> Sean Larkin: When I say a Tapable instance now, it's literally a class or an object that extends Tapable. And what's relevant to you is, aka, it's something you can plug into, right?
[00:07:25] You can plug into this. You can write a plug in for it. You can extend, modify or change behavior. And so when you think about kind of in a more drawing fashion like, even to access other Tapable instances, you have to go through the compiler, right? Because it's the top level.
[00:07:45] And so pseudocardio, let's say like you, to access a compiler, you have to do this compiler.hooks.compilation. You get the compilation back and the call back and then you say compilation.hook., whatever you can tap into.