What is the best way to structure a Vue.js application so that it can scale to meet all your users' needs? There are multiple patterns established by the Vue community and the programming community at large that can be adopted in order to make your codebases more predictable, maintainable, and extendable.
Patterns for Large Scale Vue.js Applications
AI Generated Video Summary
In this Talk, Daniel Kelly discusses patterns for large-scale Vue.js app development, emphasizing the importance of following standards and using officially recommended tooling. He highlights the Vue.js style guide as a valuable resource for styling standards and suggests using TypeScript and Nuxt 3 to enhance development capabilities. He also mentions the benefits of having a naming convention for routes and the concept of wrapping third-party dependencies for flexibility. Additionally, he mentions the app-icon component for a generic icon solution and the advantages of interacting with backends via an SDK.
1. Introduction to Large-Scale Vue.js App Development
Hello! My name is Daniel Kelly, and I am the lead instructor at the school. Today, we will discuss patterns for large-scale Vue.js app development and the importance of structuring a maintainable and extendable application. One key tip is to make your code base predictable by following standards. The Vue.js style guide is the official resource for styling standards in the Vue.js community. It provides guidelines for component naming, such as using Pascal case and prefixing base components with 'app' or 'base'. Single instance components should be prefixed with 'the', and tightly coupled child components should have prefixed names. Following these standards helps ensure clarity and prevent conflicts. This is just a sample of the guidelines available in the style guide.
Hello! My name is Daniel Kelly, and I am the lead instructor at the school. I am so very excited to be with you all here today. I have been a full-stack developer for the past 10 plus years, worked with technologies like Wearable on the back end, and of course, Vue.js on the front end. But that's enough about me. I just wanted to quickly let you know who it is you're dealing with, but now let's get on to today's topic at hand, okay?
And that is looking at some patterns for large-scale Vue.js app development, right? So, our goal during this session is to answer this question, what is the best way to structure a Vue.js application so that it can continue to be maintainable and extendable, even as it gets to a very large size, right? Why is this question important? Because we've probably all been given a task for a particular app before and had this exact feeling. We just don't know where to begin, we don't even know how to approach the issue, maybe because things are a little bit messy. So, our goal is to eliminate this feeling here as much as humanly possible. All right, we all wanna enjoy our jobs and be less frustrated.
Okay, so I'm gonna start with this key tip for making a large-scale application, that is make your code base predictable. This first tip is really not that exciting, it's really not that flashy, but to be honest, this is one of the keys, in my opinion, to building a maintainable app. Make it as predictable as possible by following standards, so that everybody knows where to look and how certain things work. So, this begs the question, where do standards for the Vue.js community exist? Place number one that comes to mind for me is the Vue.js style guide. This is the official place for styling standards for the Vue framework. Here is an example of some standards designated within the document. When it comes to naming your components, first of all, it says that all of your components should be in the Pascal case. It also mentions you should prefix your base components with the word, app, or base. So, these are all those components that you're going to be using throughout your application, and they're a lot more general use case, right? These are things like AppButton, AppTable, AppModal, things like that. Things that accept props down and events up, and probably don't rely on any global state, okay? I actually prefer to use App in this instance because it always puts my base components at the very top of my components directory. It also mentions that you should have multi-worded names for your components. This is actually even more than just a style thing, it's also to prevent conflicts between existing or future HTML elements and your new components. Another standard is to prefix all your single instance components with the word, the. These are any components that are just going to be used on the page a single time. Now, they could absolutely be used on multiple pages, but they only appear on a single instance of a page at a time. So this is usually layout type components, things like the header, the footer, the sidebar, so on and so forth. It's also mentioned that you should prefix tightly coupled child components. For example, if you had a component for an item that always existed within a to-do list, you would prefix that component name with to-do list, and then item. A real-world application of this that I used in a codebase at my previous job was I had a job form component, and then there was a special field for choosing the location where a job should be advertised called job form location map field. Okay, so this tells any other developers within the project that this component is really only meant to ever be used in the context of the job form. And they can get that just by looking at the component name. Okay, this is great, and there are some other tips on styling your component names within the style guide as well, but this is just a good sampling, and there's certainly a lot more available in the style guide besides just component naming.
2. Standards, Tooling, and IDE
Implementing standards in your project reduces cognitive load for new team members. The Vue.js style guide provides guidelines for component naming and other styling standards. The guide is currently outdated but still valuable. The officially recommended tooling for Vue.js, such as Vite and Opinion, provides useful resources. Avoid custom solutions when there are officially recommended ones. NUX3 is a reliable source of predictability due to its conventions and popularity. Taking full advantage of your IDE, installing Volar and ESLint, helps catch errors and improve development experience. IDE formatting, whether with ESLint or Prettier, ensures consistent code style.
But this is just a good sampling to kind of show you, hey, if you implement these standards, it's one less cognitive thing that people who are onboarded to your project have to think about, because they're standards that everybody already knows, okay?
By the way, just at the time of this talk, it is important to note this warning at the top of the style guide, and that is it's currently a bit outdated. Most of the examples are in the Options API only, and there are no rules regarding Script Setup and the Composition API. However, as you just saw, a lot of the things for styling don't even necessarily have to deal with one API or another. All of the component naming things could apply to either API. So this is still a great resource, but do expect it to be updated in the future, okay?
Another really great resource for standards is the officially recommended tooling for Vue.js, all right? That's found on the tooling page of the official Vue.js docs. It provides reference to things like Vite for your development server and Opinion for global state management. This might seem like it could go without saying, but maybe I've ignored some of my own advice in the past and I want to make sure you don't do the same. What do I mean? Well, one of the projects I was working on prior to joining Vue School, of course, needed global state management. Well, I wasn't thrilled about the DX that Vuex provided, and so I came up with my own global state management solution based around the Vue.Observable API in Vue 2. Long story short is, yes, there were some DX improvements. However, there were more downsides than upsides. There were caching issues that I didn't handle that Vuex would have already handled for me under the hood. There were onboarding issues when it came to moving new people to the project who I had to explain this custom solution to that if I just used Vuex they would have already been familiar with it or at least I could have just pointed them in the direction of the Vuex docs, right? So the key takeaway here is if there is an officially recommended solution for your problem, definitely think long and hard before you use anything else, okay?
So predictability from the style guide, predictability from the officially recommended tooling, and then finally another great source, I think, of predictability is the metaframework NUX3, okay? It makes a lot of opinionated decisions and it's such a huge player in the Vue.js community a lot of people are going to be familiar with the conventions that it provides. So definitely recommend taking cues from NUX3 when it comes to structuring your application or just using NUX3 to begin with. By the way, you will see NUX3 come up a few more times in this talk because I think it's such an excellent piece of software.
Alright, so tip number two is to take full advantage of your IDE. This is after all the software that you're going to be using most in order to develop your application. Number one, that means make sure to install Volar, that's probably pretty obvious. However, number two is also make sure you have ESLint installed on all your projects. I've had projects that I've worked on before where we didn't do this. Let me tell you, it was an absolute pain because ESLint is going to help you catch items directly inside of your IDE without having to wait to find out about them at runtime. In fact, it's gonna show you errors in your IDE that you might not even get hard errors for within the browser, all right?
So, for example, in this little piece of code, we're using a V4 to loop over item in items but we have left off the key. This would not error in the browser but my IDE knows now because of ESLint I should really add this key to my V4. And then the same thing down here for this Hello World component. It's being imported and registered. However, it's not actually being used anywhere inside of my template. And so ESLint is saving my end user from having to download this extra code that's never even used. Right, I get this essentially for free just by installing ESLint, okay?
Similar to this is making sure your IDE's formatting is set up appropriately. Okay, this could be the formatting that is built in with ESLint or it could be a more opinionated formatter like Prettier.
3. IDE Setup, TypeScript, and Nuxt 3
Make sure your IDE is set up to automatically format your code. Check out the 'Visual Studio Code for Vue.js Developers' course for more tips. Consider using TypeScript in your large-scale Vue.js projects to enhance your IDE's capabilities. Vue School offers courses on TypeScript for Vue.js projects. Nuxt 3 has TypeScript installed by default, making it a great way to get started with TypeScript. Nuxt also provides great file structure conventions and functionality, such as auto-importing components and file-based routing.
Okay, this could be the formatting that is built in with ESLint or it could be a more opinionated formatter like Prettier. But no matter what, make sure your IDE is set up to do this formatting automatically for you, be that on file save or whatever, just make sure you aren't having to take that cognitive load yourself. It's just not necessary. The tooling can do it for you, okay?
If you'd like some more tips and tricks about taking full advantage of your IDE in the context of a Vue.js project, I highly recommend you check out this highly rated course that we have at Vue School. A lot of people have given me really great feedback that this has helped them optimize their workflow. Okay, it's called Visual Studio Code for Vue.js Developers. And in it, we go over some of the things I already just talked about, but we also get into things like utilizing Vue.js snippets that are provided by the community, creating your own Vue.js snippets, optimizing your workflow for Git in terms of using your IDE, and a whole lot more. So definitely check that out if Visual Studio Code is your IDE of choice.
4. Naming Convention for Routes
Come up with a naming convention for your routes, even though it's not officially specified in Vue.js. Other frameworks have route naming conventions, such as the one from Laravel. Having a convention in place ensures predictability and collaboration within the team.
Tip number four is come out with a naming convention for your routes. This is not something that's specified officially for Vue.js anywhere. However, a lot of other frameworks out there do have route naming conventions. And the one you see on the screen in front of you now is pulled directly from the Laravel docs. So I could be working on a Vue.js frontend and other developers who are on my team who are familiar with Laravel could also be working on this frontend and they could have a predictable way of working with routes if I follow the same convention for my frontend. So your team might not use Laravel. That's perfectly okay. My point is have some kind of convention in place. And if you need inspiration for one, I definitely suggest you check out the Laravel docs because this convention is a really great one. Okay?
5. Wrapping Third-Party Dependencies for Flexibility
Josh Deltner explains the concept of wrapping third-party dependencies to decrease the chance of third-party login and increase app-specific optimizations. Wrapping dependencies allows easy replacement in one place, without affecting the entire codebase. It also enables extending functionality for app-specific use cases. This approach works for both functional libraries and components, providing a convenient way to implement and manage third-party code.
This is a concept that Josh Deltner explains very well in his article entitled Nuxt Enterprise Patterns Provider Abstractions. Okay? Why should we do this? Well, it decreases our chance of third-party login and increases the surface area for app-specific optimizations. You might not actually understand what that means. So let me show you with a little example code.
All right? So let's pretend we're using Axios in our project in order to make our AJAX requests. Now, Axios is popular enough that I wouldn't actually suggest wrapping Axios. I would suggest using it directly. However, it's a good and common library that I think helps people understand this pattern. So I wouldn't actually wrap this in your apps, but I would do it for similar third-party dependencies.
Okay, so let's say you have Axios. In order to wrap Axios, you could create a class called HTTP and then define a get method on that class. Under the hood, all you're really doing is calling the Axios get method. And then you could do the same thing for the other method types and so on and so forth. But why in the world would I want to do this, Daniel? I mean, I'm not getting paid to write per line, right? Well, the advantage here is that if, for some reason, we ever had to replace that dependency with something else, I could very easily just do that in one single place. So, here, we've changed out Axios for the browser-native fetch function. And the beauty is we've only had to change it out in one place, that is, in our HTTP class. We didn't have to search throughout the code base, do a bunch of messy finds and replaces, we only had to focus on this single file. And the other beauty about this is that all the other developers working on the project who are using this HTTP class throughout the project, they don't even have to know that I've updated dependency. They just continue using the HTTP class as usual, okay?
So, this is a really great solution when it comes to dependencies that you're maybe not so sure about, that you think might not have the longevity. You might be replaced later on with something else. So, I'm not saying wrap all of your third party code, but be choosy and do wrap some of your third-party code, okay? Another great benefit of wrapping this third-party code is that it surfaces opportunities for extending the functionality for app-specific use cases. So, for instance, let's say I wanted to handle all of my HTTP errors a particular way in my app. Well, at that point, it's as easy as adding a try-catch within my single class. Now, of course, this user experience isn't great, but you get the idea. I can have these app-specific optimizations all wrapped up in my class. And then when I go to use the class throughout the application, I don't have to worry about reporting these errors to the user or whatnot. Same kind of thing could be applied for a caching mechanism. All right, I think you get the idea. By the way, this also works for components and not just for functional helper libraries. So, for instance, this app-icon component I have here is actually made to make my icon solution from my app generic and even extend it so that I can use two different icon solutions at once, so you see here my app-icon wraps font awesome as well as material design icons, and I've provided a single interface that is the app-icon component for actually implementing the icons throughout my application.
6. App Icon Component and Backend SDKs
The app-icon component allows for a generic and extendable icon solution in your Vue.js app. Interacting with backends via an SDK offers advantages such as preventing typos, client-side data normalization, error spotting, and type safety. Recommended Vue School courses include TypeScript with Vue JS 3, Pina the enjoyable Vue store, and wrapping rapid testing with V-test. Vue School also offers the AI Chatbot with Vue JS and GPT-4 course and the official Vue JS certification.
So, for instance, this app-icon component I have here is actually made to make my icon solution from my app generic and even extend it so that I can use two different icon solutions at once, so you see here my app-icon wraps font awesome as well as material design icons, and I've provided a single interface that is the app-icon component for actually implementing the icons throughout my application.
Awesome, that is my time with you today. I wanted to leave you with just a few recommendations for some Vue school courses that I think will help you build better large-scale apps. Number one is the TypeScript with Vue JS 3 course, we've already talked about a little bit. Next is our Pina the enjoyable Vue store course. This is going to help you get a great grasp on the official Pina state management solution for Vue, and lastly is wrapping rapid testing with V-test. All right, by the way, we also just finished releasing this great new course called AI Chatbot with Vue JS and GPT-4. If you're interested in implementing AI into your applications, your Vue JS apps, I definitely suggest you check this out. And the official Vue JS certification has launched and pre-orders are being accepted. So this is something that the Vue School team is doing in collaboration with the core Vue team. If you'd like to prove your Vue JS development skills to potential employers or potential clients, this is a great way of doing that. Thank you all very, very much for your time. And I hope you have gained some valuable knowledge from today's talk. You all have a wonderful day and keep coding. Thanks.