New Design Pattern: The Plugin Pattern

Sep 23 10:02

I'm sitting in my office, about to make a decent size refactor to Livewire's core, and thought I'd tell you about it!


Hey everybody, right now. It is pouring rain outside my window in my office and I just love that so much. I love the sound. It makes me feel like I'm in a cozy shelter like a fort when your kid anyway. So I titled this new design pattern the plug-in pattern so this may exist or not or whatever.

But basically it's something that I've been pondering about this new way of writing code that I want to move the live work or two. And I think it'll be interesting and useful for really any project but probably more open source projects, who knows. So the idea is I'm actually coming up with this off the cuff.

So it's going to sound like like it's well thought out but it's not the idea. That all or as much functionality as you can for a core four core features inside of a plug-in or package. You should write as plug-ins for for that package what I mean by that is so Livewire offers all these directives.

So wire: click while your colon pole, you know, anything like that. I eventually would like to allow the user to register their own hooks so that you could make wire: funada Ledoux. I don't know and and the syntax might be something like Livewire dot directive register the name and then some call back or something like that.

Well, what if. Even the internal hooks. Sorry the internal directives what if they used the exact same system so that if your Source diving you're not, you know, it's not like I guess userland and whatever the opposite of that is core core software land feels. The same so an example of this in laravel would be lets say so when you register a custom blade directive and laravel.

So blade directive is the at whatever so a diff is a blade directive if you want to register a custom one, it's Blade the blade facade:: directive you pass in a name and then you pass in a callback that you know that you return the rendered HTML from when you Source dive laravel, you'll find it's not as simple like you don't find any place in laravel core that all the.

Are registered that way they're inside of these compiler traits and they're like the it or the like let's say the unless directive is a method called compiled unless and there's magic happening and do that which I think you know isn't a great experience as a source diver. Maybe it makes sense for somebody writing the laravel framework, but how cool would it be if even the core laravel?

Directives were where actual you know, custom register directed. So somewhere in their vocal cords, he played:: directive so this this could apply to so many different areas of Livewire the obvious one. The one that I the one that I sort of came to this with was custom directives, but I start to think about it how I could apply it in all sorts of different ways.

So there's custom directives. There's custom actual blade directives inside Livewire that I'd like to offer where you can register blade directives that only. Run within a live wire request. So you're not, you know messing with the global blade namespace. So there's actually only one right now that exists the at this directive for JavaScript stuff.

But but I want to make those extensible and actual plugins like right now. I have a trait called use pagination. I think that basically makes a Livewire component all. It adds functionality for for pagination. It kind of hijacks levels default pagination. So maybe there's a way that I could make this more extensible and use it in the core.

Another thought I had was data tables that's going to be something that a really common use case for Livewire at some point. I really want to sink my teeth into it and make a data tables implementation like a first-class API that you can use to make data tables in your apps with Livewire. And I think this is the kind of thing that maybe I wouldn't want in core.

Maybe I would want it to be like a composer require Livewire / data tables and it all just kind of works. So anyway, this is kind of where my brain is going and one of the founding motivations behind. This is the make more things the same principle. I think this is a Sandi Metz thing. I don't really remember exactly but I think it is Sandi Metz.

I'm probably just paraphrasing but I love this piece of coding wisdom make more things the same and this is a perfect example the things that were different before so in in registering blade directives in laravel to use that example, there's the. The way that it's used in the core. Where is this custom these custom traits with these methods and then there's the way that users can use and user land like blade colon colon directive to register your custom directives to apply the make more things the same pattern is too.

Make one unified interface for registering blade directives whether it's user register our developer registering a blade directive or Taylor creating a new blade direct at this way. So that that sort of the the plug-in pattern here's another place that I want to apply it. This is a little bit more zoomed in and a lower level.

Detail so Livewire is kind of like vue.js in that it does Dom dipping. So when live where calls out to the server, it renders blade or start renders some Dom gets the HTML back it Compares it with what's on the page and it uses a plug-in called morph Dom that walks through the Dom tree and decides if things are the same or if they're different and if they're different it only updates what's different.

So this way you're not wiping out big parts of your Dom and you know, losing focus stayed and input values and all. Stuff like that. It's really efficient, and it's really fast and this is all great. But there's lots of things I have to do so morph down provides hooks itself for things like on before L update which is like before an element is updated by morph Dom you can do stuff to it or decide to disable that behavior.

So there's these hooks that morphed I'm offers and there's all sorts of like it's really hard to just jump into this without explaining live where Corbett. Basically there's lots of places where an element is created updated or destroyed Live Wire is the thing that's doing that. And I have to hook hook things unto their and to those those places in the life cycle for everything to work.

So one example is wire: loading when you add that directive to an element, it's hidden by default, but then when live wires loading, it adds like display block or something to the elements so that it shows. So there's I have this loading manager. It's a class that basically keeps track of all the elements that have that directive attached so that I can toggle them and and toggle them all I can type of them on and off.

So this pattern if I move to this pattern instead of having these these little like Livewire or sorry loading manager dot register loading or something scattered throughout the code base if I had a unified interface that was like on before element destroyed. And a user and user land so you and you're using live where you can hook into this yourself if you want to do stuff and I can hook into it for all sorts of core functionality.

So that's a little bit hard to explain without giving specific code examples or without you seeing the code base. But just know that there's tons of instances where this would be super useful. The reason this all came about is because I'm reading Sebastian to dyn's. I never know if I pronounce his name, right?

I really should ask him that Sebastian to dyn's blog post. You just did a blog post on like using vanilla J's to solve a simple problem instead of reaching for view right up my alley. I love it. I love what he did. Forget about Livewire. He did the right thing. It's great. It's a great post. You should check it out, but I can't help but read it and think oh my gosh, this would be so much easier in Livewire.

But one thing that it was missing that he had was offline state. So he added a little indicator in the top right that shows when the connection is offline because it's okay to give you the gist. It's a status page for Flair that new era tracking app that shows I think it's just the the flare app status page.

It's like if flare is working if the flare servers are up or down I don't even. And it gives some sort of indication like red or green and he's just pulling like we talked about in the last episode where he's just hitting Ajax hitting the server swapping in HTML every so often but he listens to an online or offline event that browsers fire when computer goes offline and if that's the case, he shows a little off line indicator in the top, right so, you know that you're not getting a live update and I think that's really cool live where doesn't have anything like that people have asked in the GitHub.

So I thought well I should add a wire: And to an element so that I can toggle. So let's just say it works like while you're loading if if the thing is online than whatever that element is its just doesn't show if the app goes offline then those elements that have a wire: offline will show so I went to add this and I thought oh man, I'm gonna have to register this just like I did the loading indicator.

So everywhere. I handle wire loading. I have to handle wire offline. I thought if I moved to this make everything a plug-in make everything extensible make everything hooks that I could make one hook. That that is just like, you know, I could just hook in. Okay, I can have one file that's just in charge of the offline functionality and hook into the places.

I need to hook into them. So maybe this is called the hooking pattern or whatever. There's probably a million different things here. But the way I see it, we're all so it's all skirting around this principle of like make everything extensible make everything lifecycle hooks so that the users can register their own things in a custom unified way and you can too and it's all founded on the.

Support of make more things the same. I hope this was interesting for you. I'm literally about to go right this refactor. I just wanted to let you know what I was doing before I get to it. So thanks for listening as always some outro music that doesn't exist now then identity.