If you're building a module that needs to execute code at runtime, you will need to inject the Nox plugin from the module into the application. Whether it's because you want to provide a global function or use Vue plugins or implement some app-related logic when the plugin is triggered. And we can easily do that using the addPlugin function or utility that is provided by NoxKit. This function provides a straightforward implementation to add Nox plugins to the application's runtime.
And just like anything else that needs to be injected to the application's runtime, it has to be inside the runtime directory. ts and inside of it, I will start a new Nox plugin just like I'm doing it inside a normal Nox app. And just like that, I have a plugin over here. But here's the trick.
When you're doing it from the medjool, it can be a little different from creating a local plugin directly in the app. as the auto-imported Noxed built-in functions won't work in published modules. And in our case, defineNoxedPlugin is not defined here, and it has to be imported from imports, so I can import it just like this. defineNoxedPlugin from hash imports.
And this imports over here exposes every NoxedAuto imports. If we hold command on Mac or Control or Windows and click on imports, This code will take us to this imports entry file, where we will find all these auto-imported functions being exported. And among them is the defineNoxtPlugin, of course, right here. So, now that we created a plugin, let's just console-log something, console-log, let's say plugin, worked.
I'll head back to the module definition and register the plugin to the app. To do so, I'll use the addPlugin function we imported earlier, like so. It accepts an object where the first option is the src option. And it's the only required property in this plugin.
It accepts a string with a full path to the plugin. And just like we learned in the previous lesson, we can import createResolver from NoxtKit and use it just like this. I'll distract resolve function out of it and createResolver. js because it will be transpiled to mjs automatically by the builder and now when we run the app like so once we open it the plugin will log the message to the console Cool, but that's not only it, because AddPlugin accepts more options, like the Order option.
And it indicates the position of the plugin in the lineup. As you probably know, plugins can run in parallel or sequentially. This option allows us to gain control over where we want this plugin to be positioned among other sequential plugins. The default value here is zero, but if we want this plugin to run like the third one in the lineup, we can just add 3.
And in case we want to append the plugin to be the last one registered, the addPlugin function accepts another object for options, like so. And in this object, we can set append to true. And just like that, it will be the last one registered and triggered inside your application. If you've been following me all along throughout this course, you should know that I would never leave interesting concepts like plugins to just a few console logs explanation.
Let's use this AddPlugin utility to inject a plugin that actually does something useful. js Nation code challenges. If you haven't heard about it, it's this fantastic free virtual event brought you by Vue School. It's an opportunity to connect with community leaders and experts in the Vue ecosystem.
It took place back in January, but it was really cool. If you missed it, you can watch the replays right here. Anyway, like I said, I decided to copy one of the code challenges and do some modifications to make it more NuXy. I'll go through the implementation real quick.
So we are using useFetchComposable to fetch 10 random codes from Codetable API. And deep option here is set to false because we don't need the data to be deeply reactive for anything. And we are using onRequestError to handle the error. Ish.
I mean, we're just pretending we're handling it. We're just logging it to the console. And then we are setting the retrieved data to a new codes variable ref. And I have a method here to refresh the codes which is refreshing the entire data like so.
It's just using the refresh function returned by useFetch. And finally the sorting logic to sort the data by descending or ascending order. Now let's imagine the app developers wanted a module that would allow them to implement infinite scroll feature. where users get to see additional 10 codes added to the page once they reach the bottom of the page.
And now it's your turn as a module author to make this module available to the Noxed community. Let's make it happen. There is a package called View3ObserveVisibility, and it provides a Vue plugin that registers a pre-configured Vue directive. Then we can normally apply this directive to any element like so.
It uses Intersection Observer API under the hood and it allows us to trigger a callback function once the element is in the viewport of the user. So let's grab that package and install it in our module. Then we can use Nuxt plugins to register the view plugin from the package. ts and I'll start by importing define Nuxt plugin from imports.
Then I'll export the plugin, and now we can import the package, and we will use the NuxtApp parameter passed by the plugin to access the ViewApp instance. Then use the plugin, without passing any options. Then head to the module definition, import, add plugin, and inside the setup function, we can use it like so. But we would need to resolve the full path.
to the plugin, so we would need the create resolver from NoxKit. Let me just close that up. Then we use the resolve function to resolve the full path to the plugin. And since this third party package was intended for client-side rendered view apps, we might face some trouble with it in our Nox server-side rendered app.
Think about it. This directive is to detect whether the HTML element is showing to the user viewport on screen or not. So since it's only making sense on the client side, we probably should limit this to run on the client side alone. And we can easily do that by using the mood option, which allows us to load it in both client and server side if left undefined or set to all.
And we can limit it to only server or only client. And in our case, we need to limit this to client. Another option to limit the plugin to a specific rendering mode is by adding . server after its name, but I'll just keep using the mode option here.
Now, when we use this directive on HTML elements in our template, the server will face a trouble understanding what the heck is this supposed to be, because it has no knowledge of this directive. After all, it's only registered on the client side. So, we need to provide another Knox plugin that runs only on the server, which provides a directive with the same name, but does nothing on the server. Let me quickly do that behind the scenes.
So I created a new plugin called Observer Stop, and this plugin just registers a new directive to ViewApp, which is completely empty. It doesn't do anything. It's just for the server to find and doesn't say that this is undefined. So I'll go back to the medial entry point and then register this new plugin.
Like so. Observer Stop. And this will be only available on the server. And we're good to go.
Time to test. View, and then right over here in the Footer Dove, which is this one, may the force be with you, I'll add the directive, which is vObserveVisibility. And then we'll pass the callback function. Let's call it Load More Codes.
And I will create that. Let me close this up and then go right below the Refresh Codes. create a new function and here I'll use the execute function passed by the useFetch right over here which will allow me to re-trigger the useFetch call to API again like so and once the execute function is called the reactive data object returned by the useFetch will be updated with the new data so I'll create a new variable over here called newCodes and set it to the new data value then update the main code's variable ref, like so, to make it an array of the current codes plus the new codes. If you are familiar with the IntersectionObserver, you will know that the default behavior will trigger the callback immediately upon the initial page load, which would cause our method to fetch an additional 10 codes even before the element appears on the screen.
According to the package documentation, the callback function will pass two arguments. The first one is isVisible, and the second one is Entry. Then we can use the Entry's intersection property, which tells you how much of the target element is currently visible. So we can add right over here an if condition to check on the Entry intersection ratio, if it's anything above zero, which means that's on the screen.
In that case, load this logic over here. Let's see that in action. Yarn dev. Okay, looks like we missed something.
I'll check on the error. Right, so I guess we wrote down this incorrectly because it shouldn't be observer visibility, it should be observe visibility, like so. So I'll terminate the dev server and run another one. And we are live.
That's good. Now, we will scroll to the bottom. And we should grab an additional 10 quotes every time we hit the dev with the directive. That's working like a charm.
And we successfully allowed the app to have an infinite scroll functionality. And that's it for normal plugins. In the next one, we will talk about plugin templates and how to use them.