Putting It All Together: Advanced Feature Integration in Modules — Transcript

Transcript of the free Vue.js lesson Putting It All Together: Advanced Feature Integration in Moduleswatch the video lesson.

Alright, let's get more technical with our module. But before we start, a quick heads up. This video might run a bit longer than usual, and we won't be introducing any new concepts for modules. Instead, I'll really take my time to apply what we have learned so far and integrate a new feature into the module.

We'll go through planning the feature, executing the plan, and adapting to the module's structure and nature. So if you're eager to explore the next module concept right away, feel free to skip ahead. Just know there is some valuable content here that you might find useful even beyond this specific module. And now let's get to it.

I'll start by bringing up the terminal and run a small command to get inside the Playground directory and then npx noxie analyze. What that will do is create a production build and Nox will analyze its data then provide us with this magnificent view that we're about to see. This Noxed bundle stats presents two types of bundles. The first one is Nitro server bundle stats and the second one is Client bundle stats.

Let's have a look at the Client bundle stats. And what you're looking at is the result of Noxed, Vite and Rollup working together to break down your application into separate chunks. This way, Noxed loads only the necessary parts of your page, rather than loading the entire application for every request. The process is called code splitting and it's a brilliant approach.

These are all the chunks inside our application and the biggest one of them all is the entry to JS chunk. It has so many things. This chunk is the browser's access point to all the JavaScript code in your page and it will be loaded with every single request regardless of which page has been requested. And it usually has all the JavaScript files that most probably will be needed in all requests, like an app header or an app footer.

But in our case, since we're using the module starter template, we don't have any components that we are using constantly. But I'm spotting here a Nuxt error page to view file. That looks like a component to me. And it is indeed a component.

If you are curious where it's coming from, it comes from Nuxt core code base. Let me show you. I'm using VS Code extension called search-nod-medules, and this extension over here allows me to do something like this. So I can search in nod-medules for Nuxt, then go inside any directory I want.

In our case, I want to go inside dest, and then app, components, and here we should find our page, which is Nuxt error page. And this is it. view file in the project root directory. It uses defined async component from view to dynamically and conditionally to render either a 404 page or a 500 error page.

But why is it included in the entry to JS file? Well, it's because unfortunately any request might end up with an error. Now, I'm thinking that it would be very beneficial for our module to empower users to have more control over their chunks. So let's say the user would like to split this NuxtErrorPage component into a separate chunk outside of the entry to JS, reducing the entry to JS file size.

And I must say here, I'm not saying that you should do this, I'm saying that we should empower our module users to be able to split their chunks the way they see fit. And since Nox uses Vite and Vite uses Rollup under the hood to bundle the app, let's check out Rollup options and see if it has an option to control chunks. I'll put manual chunks. That sounds like what we need.

It looks like there are two ways to work with this option. The first one is using manual chunks property and pass the chunk name and all the dependency names you want to split. And the other way gives you full control over which assets you want to chunk, so it's not limited only to dependencies, you can chunk anything inside the application, which is exactly what we need. So the function form of this configuration option is our way to go with this.

And it's fairly easy to reach out to rollup options from Vite, so let's check out Vite and look for rollup options. And this is our way in. ts file. I'll go down here and start accessing the properties that I need.

And finally, the function form of manual chunks option. And according to the documentation, this function will pass a string that represents the file name including the full path for each file inside the app. So I'll follow the docs and name it underscore ID. View.

And if that's true, return a new chunk that is called ErrorChunk. Now, let's see if that worked. I'll zoom in a little, check the Client BundleStats, and there it is, the new ErrorChunk. that has our component inside it which is the next error page and also it has all the related dependencies including that view dependency which originally was inside the entry to js chunk and that really brings up a question since this new chunk has some indispensable dependencies like view wouldn't that mean this new chunk will still be loaded with every single request the answer is yes The manual chunks option in relab will always split the chunks you need, but it will also include in the chunk all the related dependencies.

I'll pause here to highlight a very important note. When dealing with manual chunks and code splitting in general, you must know what you're doing. Copying exactly what we do in this lesson might not be the best approach for your application. Take the time to carefully split your chunks and extensively test before making any updates to the production environment.

Rushing this process can lead to quick complications, causing delays, and unnecessary requests. And keep in mind that Nox defaults are great for the majority of projects. It's a good idea to reduce entry to JS file size, but all I'm saying is, be careful while you're doing it. Now, back to topic.

The goal of this code over here is to enhance the application performance by optimizing the client-side bundle chunks. Since we have emphasized how important it is to be careful, I'll limit this logic to be executed solely on the client-side, leaving the server-side chunks untouched. So how am I going to do that? Well, I need to interrupt Nox lifecycle when Vite is working on the application bundle, and then execute my code only for the client-side chunks.

And this is where we need Nuxt Lifecycle hooks. There is a hook here called Vite Extend Config and it's passing two parameters. The first one is for Vite Configuration Options and the second one for ENV Object. This ENV Object might be the one that we can use to determine whether we would like to run this on the client side or on the server side.

But we're not sure yet. Here is how to be sure of the parameters passed by the hooks. There is a link over here, let me scroll up, called Schema Source Code. Press on it, it will take you to GitHub.

ts file, search for the name of the hook that you're looking for. And right over here, you can see what is the ENV parameter all about. It is an object that has two properties, isClient and isServer. And this is how we can determine which environment to run our code in.

So since we're using now Hooks, I'm just going to comment this out and then start with our new implementation. Config and work with our Hook. The first parameter is the VeedConfig and the second one is the ENV, but I'll just pick the IsClient out of it. So let's do an early check.

If IsClient is false, or this is not a production environment, Don't do anything and just skip. Now let's start drilling the config. So it will be config, build, roll of options, output, manual chunks, which is a function that's passing an ID of a string. And here we can just copy this over here on comment and we're good to go.

But I'll just silence TypeScript warning for now. This will surely work. But the most important part of it is to work from within the module and allow our users to split whatever chunks they need. So I'll grab everything and move it to our module entry point.

We'll just remove everything from here, including this commented code. We don't need that anymore. Close the config file and then head to our module entry point. I'll paste everything in the hooks property like so, then convert it to an object with the key as the hook name.

and we'll set it to an arrow function. Like so. So let's plan how our users are going to pass the chunks they need to our module. The way I'm imagining this is that users could pass an object and each key in that object will be a chunk name.

And each chunk name will have an array of strings that represents the modules they want to include in that chunk. view and maybe a plugin and then chunk2 will have something else. That will allow us to loop over this object, take every key as the chunk name and check if the ID includes any of the names inside this corresponding array. Cool, sounds like a plan.

We first need to add the option to the module options interface right here, so that will be a manual chunks option. and should be an object where the keys of that object are strings and the values of those keys are arrays of strings then we should add a default value for this key so that will be manual chunks set to an empty object cool we're good to go but we get one problem though inside the hooks property we don't have direct access to the module options we have direct access to the module options inside the setup function scope right over here so I would need to move this logic over here to the SetupFunctionScope. So this will be deleted like that and as we learned before we can use the Nuxt Hook syntax inside the SetupFunctionScope in order to reach out or to listen to Nuxt Hooks. So it will go like this.

Nuxt Hook. I'll paste the code and change this to a comma. Like so. And this should work exactly the same.

the next step would be storing the option passed by the user in a variable now let's make this dynamic we don't need this anymore and let me quickly grab this example over here a little bit closer to where I will write the code this will help my brain imagine how the manual chunks object would look like so I think the best way to loop over the manual chunks object is by using object in trees This will transform every property in the past object over here into an array of keys and value bears. And the whole thing will be wrapped inside an array, so multiple properties would look like this. Okay, so now with the implementation, let's get to it. The first thing we will do is to loop over the chunks array that was created by object entries and set each chunk name with its corresponding chunk IDs to a variable.

Then we will loop over every chunk ID inside the chunk IDs array and check if the ID parameter passed by Rollup's manual chunk function includes the chunk ID passed by the user. If so, then return the chunk name which Rollup will use to create a new chunk with that name. Now I can delete the commented code and I'll add one final check here to the if condition so if the chunks array is empty just skip the whole thing as well. Now time to test.

ts and pass another option for manual chunks and let's call it RootComponents. And in this chunk I'll pass two components, the NuxtError page and another called AppDudeView. And don't worry about this error over here. This should be gone by running yarn dev prepare.

Oops, looks like we missed something. Yeah. I think VS Code added those optional chaining without my consent. Now let's try again.

Yarn Dev prepare. This should work. And it did. Now let's analyze.

Check the client bundle. And there it is. Our root components chunk. And it has the Nuxt error page to view.

And where is the app to view? There it is. But it's a bit tiny. That's cool.

Everything works. And with that feature in our module, our users can easily pass in as many chunks as they want and the module will split it for them using lockstokes. And that wraps it for this lesson and I'll see you in the next one.