 Hi guys. So I'm Arnav. I currently work at Zomato and my work has nothing to do with UJSI. I work on the mobile team at Zomato. So that's why I start with why I made plugins in a language that I don't use. So let me show you a sample of a site project building. So it's a website called sharetime.in. It helps me schedule meetings with people in different time zones. And I needed a component that would update itself every second. And I needed it in a lot of places inside that website. So I built something like this. You have a time object in the data. You have a method called update time. And there is something called timers. Now if you have used a view before, you know that there isn't a key called timers inside the view instance by default. But that's what my plugin does. If you add a timer for update minutes with an interval of say 30 seconds, repeat it through every 30 seconds, that function is going to run. And in fact, if you use TypeScript, it's even easier when annotated with timer at certain interval and it's going to run like this. So that's the first time I actually made a plugin for view itself. And I've used it in a couple of websites since then. And then eventually once I had to build it, so I found a startup where we had an online ID and it has to save a lot of things last and port last out port. It's like, you know, it's an ID. So it has to save a lot of stuff. It has to save something, the local storage, some local footage, etc, etc. And I wanted basically my entire Vuex state to get saved to a storage and get restored when you open that website. So for that, I built something called Vuex persist, which again, my end goal was that it should be like only two, three lines to incorporate it and my Vuex store to get saved. Using it is very simple. You just construct an instance of it. You pass the storage to it. And as long as it is off the storage data, which is it has get item set item functions inside it, you can pass it an object to it. And when you create your Vuex store, you pass that on as a plugin. And it's it. In fact, you don't even need to be using Vue with the Vue CLI. Even if you are using Vue just by writing script src in your HTML file, you can still use this. So this is something that actually got pretty popular after I listed it has a lot of downloads, a lot of projects on use it. And so that's when I thought maybe I can give a talk or make plugins an expert enough to say that. So start with the basics. So what are plugins? So in the world of Vue, when we use the word plugin, there are three kinds of things we mean, and we could of course differentiate between them. So there are Vue plugins, which, you know, adds functionality to the Vue framework itself or the Vue components. Okay, then there are Vuex plugins. Now Vuex plugins, of course, you can use only when you are using Vuex. And what they can do is you can trigger certain things happening when the state of your Vuex is changed. And finally, there are Vue CLI plugins, which has been popular ever since Vue CLI 3.0 was released. So you can basically create, you can add support for new languages, basically, the entire Vue CLI build step where your project is compiled and bundled, you want to make changes in that pipeline, you can create a Vue CLI plugin. So I would not be speaking a lot about Vue CLI plugins, because it's a very different kind of a thing. It's about how your project is compiled and not about how it is run. We're going to be discussing more about Vue and Vuex plugins. In fact, Vuex and Vue router, which are mostly used themselves are also Vue plugins. So how do you recognize what is a Vue plugin? What's a Vuex plugin? So when you whenever you see documentation, which looks like this, that say, an example plugin called Vue boom, you import that and the documentation says that you write Vue dot use boom. So these kind of things are Vue plugins. Vuex plugins, you would usually see the documentation which goes along the lines of this, that you import the plugin. And when you are constructing the store, you pass it into the array of plugins. And Vue CLI plugins, usually you would find documentation which looks like this that you do Vue add, let's say a plugin called Crackle, or usually install it using npm and then invoke it. It can run some code generation, it can add some back steps and all of that stuff. So what exactly can these plugins do? So what a Vue plugin can do is that it can add some, you know, global methods of properties to the Vue object itself. It can add new directives, filters or transitions. So we have got a lot of transitions in Vue by default, like slide transitions and fade transitions exist. If you want to add your own ones, you can do that. Directives like Vue if V4 can add your own ones like that. And they are in fact, you know, there are a lot of libraries out there which do specifically these things. You can add some mixins. So I think last stop, there was some discussion about mixins. So you want a particular mixin to be available to every Vue component in your project, you can put that mixin inside a plugin and put that plugin into Vue so that mixin is available on every Vue component. And finally, you can add things into Vue.prototype which means those methods will become available to every instance. So usually people do that with Axios. They put Vue.prototype.Axios equal to Axios. They do and then in every instance of Vue, you can use this.Axios. It is a reference to Axios like that. So those kind of things, that's usually one of the things that Vue plugin can do. So what a Vuex plugin can do, it does a really very simple thing. It can listen to mutations and when the mutation is triggered, the Vuex plugin can decide to do something like save the state into local storage like my plugin does or you might want to trigger a new mutation or you might, you know, want to validate the user token every second so you can do that. The state is changing like that. And Vue CLI plugins, like I said, they can add new webpack plugins into your build structure. They can add resolve configs and they can add or modify the order of tasks in which your project is getting built. And they can also have transformers which can transform your code. So if you install the Vue TypeScript plugin into a Vue.js project, your existing JavaScript code gets transformed into TypeScript code. Those kind of things will do by that. So let's take a look at how do we build Vue plugins? So first of all, we need to, you know, answer these questions, which of these things we need? Do we need double method properties? Do we need filters, transitions or directives? Do we need any double mixing? Or do we need any instance methods? So the plugin usually looks like this, you export your plugin from your MP module. It is supposed to contain an install function. That install function is going to get run when the Vue.useline is getting done. And at that stage, you have the access to the Vue object and with which you can do these things. You can add a global function like this to Vue itself. You can add some directives or filters into Vue. Now, these are things that you can do at every component level also. But if you do it here, it's available across your entire application, right? Fine. And then if you want to add a mixing, so you can add a mixing like this and there's a created function. So this created function will get run for every component inside your app. And you can use the prototype to inject. There's a short hand syntax that exists if the MP module that you're building contains only the plugin and nothing else. Sometimes you might be exporting the Vue plugin plus some other things. So in that case, you can add those things into the my plugin object apart from the install function. But if the install function is the only thing that you want to export, then you can just export that. This syntax also works. If the order is a function, then you treat it as the install function. We'll actually build a view. But for that, let's take a look at how Vue's plugins are built. And we'll build both of them. So when you build a Vue X plugin, these are the things that you need to think about. What do you want to do when a mutation occurs? And do you want to do different things for different kinds of mutations? And do you want to commit another mutation when one mutation happens? And it's very important to escape the recursive cycle, you might end up because the mutation that you will run will trigger your plugin getting run once again. So you need to figure those things out. So everybody who has used Vue X would have basic idea about this. So your component can dispatch actions, actions can lose asynchronous stuff like up to the API, then they can commit a mutation. Mutations are the only place where you can change the state. And when the state changes, there might be some re-render that's happened on the component. One directional flow of data. What in this green box, the only place where our plugin can hook into this lifecycle is at the mutation that's where we can do anything. So the plugins you write like this, you can subscribe to mutations. When you subscribe, you get this function, which has the mutation state. What happens is that you can read the value of mutation dot type, which gives you the name of the mutation that was run. And mutation dot payload will give you the value of any payload if there was in a mutation, mutations can be payload less. And the value of state that is coming into the function, just keep in mind that that is the state after the mutation has taken place. So this is going to run after the mutations taken place. So you get the change state, you don't get the previous state. So if you want to prevent a mutation from happening, that is not something you can do with a, you can reverse it maybe, but you can block a mutation from happening, you just get to know that it has happened and do something else after that. Okay, if you need a plugin to block the mutation probably not a new UX properly. One thing to keep in mind is that, like I said, you can commit further mutations from here, that would result into this function running again. So you need to filter the, you need to not run it again for the my mutation being done, because that's a mutation and again, keep in mind that if you are on strict mode that when you're developing usually people turn on strict mode for VJS. So changing objects inside the state directly, state dot X equal to Y or placing the state of that those things do not work in the strict mode. And that's why like, if you don't use strict mode, you might end up writing like this. And sometimes it might work, but sometimes you will do your store if you write like this. So it's best that you have strict mode turned on. And when you build your plugins, you automatically will end up creating mutations for making changes and do it rather proper. Okay, so again, do we build? Remember this to it? Got very popular recently. Yeah. So, so years of presenting at conferences has taught me not to actually do a live demo. So I did the demo 10 hour back and I have still recorded it. So you're going to make it a plugin called CSS debug. Okay, I don't type that fast. That's 2x. And we're going to export a function that function is going to have the view object. I'm going to create a mix in global mix in. So what I will do is elements are mounted. We have published this module already, you can install view plugins, CSS debug, and give up all your CSS in your code. We'll see that live happening. But before that, how about we take this evil approach to UX plugins as well? So I don't know this. Okay, so let's make a plugin. So it's called UX plugins store flash. And again, this is also 2x. So sorry for that. So every time there is a mutation background is going to go red for and wish that as well. So actually have a project size a bit. This is a website called realworld.io. It's a it's a copy of medium, you can build it using any framework, just to brush your skills for framework. I really love that project. I think it's out. Let's go to this website. So yeah, it's how it looks like. It's a medium clone that articles and trash articles, of course. So let's do is go to in.js. And what did we name our import? Let's do about the store one. We're gonna import that as well, import store flash from and we'll add that into plugins here. What do we have? Let's change the state. So you can debug your entire app like this. I mean, of course, you guys have better ideas of making plugins, but I just want to show something that you can really quickly build one line. Yes, right? To my presentation. So just for your information, I do use nano. I don't use them because I'm not a 10x engineer. And I'm not even a 2x engineer. I just play my videos. So coming to some of the important aspects of when to make plugins. Now this is really important that you should not just keep building plugins just because you know how to build a plugin. I have built a few plugins which like these two ones, nobody uses them because so should we make a mix in and we put it into a plugin and we make the only way to use it is by the plugin or can we actually make the mix in separately available as well? That's also a question in mind. So you just decide whether the functionality that you've introduced makes sense only to some components in your project or to all components in your project. And that way, or the best thing you can do is, for example, the view plugin timers, if you go and take a look at the read me, I export the mix and the plugin both the module. So you can use it as a plugin in which case it will be available on every component. You can use it as a mix in and only those components that you want as well. And we were talking about some enterprise grade projects, you get 400 500 view files, some places should not introduce mix into them because that function is going to get run every time is a bigger and time cost. Should you make a plugin or should you just create a function and export it as a model? That also is something that we need to think of. And what you have built, does it make sense only in the view construct of things? Or what you have built is something that is very general to web development in nature. And I think this is a very deeper question is that a lot of times when we are building up with the framework, we forget that we are just doing web development. The DOM is still there. That was still there. What has not crashed? So sometimes you just make something really generic can be a function, you can import just a simple empty module, you don't need to make a plugin. But yeah, if it is, if it is related to how the view lifecycle works, or if it is related to how people will create filters like or directives, in that case, feel free to go ahead and create a plugin, right? I have a bit of time. So I test for your plugins. So now that you have built a plugin, how do you write tests for your plugins? I'll just drop down. So this is this is my view timer one. So thing is the test that I've written, they are not really like, how you write a test for a plugin. I think the best way to do it is in your plugin inside the test directory, create a sample view app uses your plugin and then test the components of the end functionality that you need. So it's similar to that. So create a normal timer component. It's written in TypeScript, though, but I think hopefully it makes a bit of sense. So I have just written my normal test. I've used JS DOM to make the documents available in Node.js. So I don't need to run this test on phantom or something like that. It runs on Node itself. And it just we just check we mount the timer component and the timer component supposed to update in 200 milliseconds. So in my test, after 500 milliseconds, I just test that the value has changed. So I mean, I'm not really testing my plugin itself. I'm putting my plugin into a view component and then testing that component that you will get very good coverage across your entire wire up your test like that. I've written some tests for the Wex plugin as well. Wex plugin again does similar things. We have got created a store, which has some values of the number of dog bugs and number of cat news. And it runs some mutations. And then I just check if the inside the saved store, whether the value has updated or not. Again, simple node level test. In fact, this test does not require view itself. It just use it just uses Vuex to test it. So it just the view part of it. So that's about tests. And I think this is very important is that when you have written a plugin, our distribution of when you distribute your plugin, you could distribute it as common jays or ESM or UMD. Okay, if you distributed as only common jays, then people would be able to use it only when they build their project via Vue CLI. But if they simply want to, you know, script src, they your module and they just want to. So in fact, if you have looked at your documentation, you can use view and Vuex together without using Vue CLI. You can just script src unpackage slash view script src unpackage slash Vuex. And you don't even need to write view dot use Vuex. The CJ script automatically includes itself into view. You just need to write the lines one after the other first import view and then Vuex. And you have Vuex setup already. So if you look at the stats, so sometime back there was an article on like, whether view is used more or will react is used more. A lot of people commented on some frameworks like view and reactor that these frameworks, a lot of people do not necessarily go and install it from npm. The npm stats might not be a reflection. If you go and look at the charts of JS deliver or unpackage, there are a lot, there are like the number of downloads going to billions. So a lot of people do use view directly inside their browser. Although that's not very good for performance, but if it is solving their purpose, your plugin could probably help those as well. So what we should do is I'll give you an example of my plugins where I have written them actually in TypeScript and I have distributed them in such a way that they can be used by people for using JS or TS and they can be used directly inside the browser or with the, you know, the view CLI structure. So what happens is when I build my modules, the disk folder, it generates a CJS folder inside which there is the common JS version of this plugin. There is a ESM folder which contains the ESM version of this plugin and then there is a UMD folder which generates the UMD version of this plugin. Finally, the .d.ds files are also separately exported types and my package.json, I have specified all of these things. So my main points to CJS because when somebody is using it via node, that is what they want. My module one points to the ESM one. So if somebody is using a fully ESX way of using it, they will import it from the module one rather than from the main one. If somebody is using something like Bower, nobody uses it anymore, but if somebody does or if you publish it in a JS delivery package, etc. So browser, we have a remap. So if somebody tries to access diskcjsindex.js, they are getting the UMD one. If somebody tries to access ESM, they still get the ESM one. And I have linked to the main files for unpackaged and JS delivered. So when I publish, they pick up the main files. So people can simply write unpackaged.com slash uxpersist. They don't need to specify the minified or the unminified and all of that stuff. Not milky pick that up. And the typings folders are also specifically mentioned out there. Usually building something like this is not as complex as you might think, distributing for all of these things. I have used rollup. So they just just define the output, the format and the target and your source is going to be still the same. You define a format for UMD, UMD min, ESM, cjs. That's it. You've got four things built. So when I'm publishing it, it's available for all the formats. Most of the view and vuex plugins that I have built, I usually do it this way. Finally, documentation. I mean nobody's going to use your plugin if it's not documented. And by documentation, it just does not mean like an automated JS doc. Not just that. That should be there. Okay. But if you're using TypeScript, even that does not require a JS doc, et cetera, automatically gets generated for what arguments and function names and all of that stuff. But what's important is user writer usage guide, step by step, how do you get started with? And we all being from the view ecosystem, I think you has one of the best getting started guides across all the frameworks and it has been one of the reasons why a lot of beginners get attracted to view. So I think it is on us when we add things to the ecosystem to stay true to the ethos of the ecosystem and write user guides. And for that, we have the oppressed. So we can use you press to build them. I can show you an example of that. Yeah, the UX, it looks exactly like all the new documentation. You have a, you know, and I can even highlight code somewhere. Yeah. So which line, I don't know if that highlight is one of the lines in that stuff. I mean, you can write really nice documentation, you press. So definitely when you're writing a plugin to that. So yeah, I think that's it for my side. That's all I had for UNQX plugins. You can put it if you want to. And this presentation will be available on speaker deck. So we can have about five questions for Arnav before we break for lunch. You specified for the mute for the mutations, like plugins for the mutation specifically I'm saying the mutations are mostly application specific, right? And those existing in the plugin seem a bit, I wouldn't say the example in the plugin. I just wrote rotation type equal to something just for an example. Say, but what you can do is so I'll give you an example of you can make the consumer of your plugin supplier list of mutations on which it is supposed to be saved. Okay, so your plugin is at a stage where the rotation happens, okay, my plugin can't know from before and when it is going to get consumed, what mutations will happen. So that values also you can take from the user because you can add a configuration step for your plugin in that case. So what happens is like the easiest way to use this process plugin is we can just write plugins and you can add that. But what I have is there are some keys when I am constructing it, there are certain extra keys. So for example, there is one called filter. So this filter is a function that people can add and this will basically take the mutation type as an argument and return a boolean so you can add your own filter function. And for those mutations, you want to save your state as those those you don't want to those things you can add as but yeah, your plugin should not be opinionated on what other questions. Yeah, so when you're building plugins and shipping some view components, so what do you suggest you should ship dot view files or bundled files. So that's a good question. I think we had a discussion about that sometime back also. So some places what you do is I don't know about view plus bundled but I do ship both the ES6 and the ES5 version usually and the UMD builds they are in ES5 and the CJS ones and the ESM ones, they are in ES6 and I usually write a line inside my read me that you know you have to turn on transpiled dependencies for this module. So because I feel that there are a lot of projects which are not transpiling down to ES5. So if they use the ES6 version of my plugin, they will save a bit on the bundled sites like those polyfills will not get added for them. But there are a lot of people who are transpiling their project to ES5 and when they're spelling their entire project to ES5, why not transpile my module has been along with that. So that's like what I feel. But I have not, I have not shipped dot view files directly. I have I did that with one of my plugins and a lot of people came up with problems like they were not able to buy that and all of those issues were there. The dot view files directly I have not shipped it. So mutating like adding a global mix in basically if your plugin is adding a global machine, it affects all the components and it can basically integrate the performance of that application. So should we use global mix in or if we are using global machine, what should we do to convey that it can be it what it can do. Okay. So I think like I said, I prefer doing is having it in the readme itself is that you can use a general document that you know, you can use the mix and separately in a independent component as well. And I think it is kind of imperative for me. I should add a line there that use it in every one of them. Then we will cut the cost wall just that makes it function to just simply be that key to pick up the property and run even if it is empty for a lot of those plugins. So that is there. I in my experience in all the plugins that I've used, there is rarely I found a plugin which is supposed to be run on every one. Usually, there are very specific cases that you need to run them on certain kinds of components because when you have built a project like the grid lab one was being shown, there are going to be at any point of time on the screen, there might be all the components itself are entered. And there is hardly going to be any functionality that is needed for all those 2000 components at the same time. And if there is then probably those kind of things get added to users except for time. So in that sense, I think putting a mix and inside a plugin is not really one of the best use cases, probably adding a transition or adding filter, those kind of things are more value. So what keywords or tags you suggest for plugins on npm and GitHub so that they are visible and discoverable when you search them. So I mean, I don't know, I haven't really gotten level of doing SEO for the plugins yet. I mean, I'm just happy one of them gets used a lot. And there are already enough GitHub issues to keep up with along with my days off. But I mean, I just follow one thing is I write them in the format of view hyphen plugin, hyphen name plugin, and UX plugin, hyphen name of plugin, something like that. That's usually the format that I prefer. And in tags, I just tried you again, then sometimes like, like, if I have like timer, like, right, timer, search on npm, not really worth very well.