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 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
Standards are crucial for achieving predictability and maintainability in a code base. The Vue.js community provides several sources of standards, including the Vue.js Style Guide and official libraries. Personal and team-wide standards can complement community-wide ones. Alternative component structures, like an almost flat structure, can work well for large apps. Adopting a standardized route naming convention can make routes more predictable. Miscellaneous tips include wrapping third-party libraries, creating SDKs for APIs, and auto-registering components globally. Thorough testing is important, and Vue School offers various services and courses for becoming an expert in Vue.js.
2. Achieving Predictability with Standards
When it comes to building a scalable project, predictability is key. You want to be able to easily locate and address feature requests or bug reports in the code. Predictability also means knowing what tools and data are available at each location. Having a predictable code base is important because it eliminates confusion and saves time. While a code base can't be completely predictable or understood as a whole, predictability is about being able to focus on one piece at a time. Standards are the key to achieving predictability in a code base.
Anyways, that's enough about me. Let's get to what you really came here to hear about today. And that is what is the best way to structure a Vue.js application so that it is maintainable and scalable the more it grows?
Well, if I may be so bold, I'm going to try to answer that often asked question with a single word. And here it is, predictability. When it comes to building a scalable project, you want everything about it to be as absolutely predictable as possible. What does that mean on a practical level, though? Well, to me it's about the ability to go from a feature request or a bug report to the exact location or maybe a few multiple locations in the code where said feature or bug report can be addressed. Not only that, I think it's the ability to know what tools and what data you have access to at that location in the code.
Now, why is this important? Why is it important that we have predictable code bases? Well, if you're anything like me you've definitely felt like this before. You've opened up the code base in your editor, and you've been assigned a task and you think I don't even know where to start. I'm lost. I have no idea what I'm doing and yeah, I think we've all been there. Maybe it's because we're new to the team. Maybe it's because we're new to a project and maybe that's a little bit more understandable. But maybe it's even a project we've been working on for quite a while, and we just don't even know where to start. Well, that's the goal of a predictable code base is to alleviate this experience as much as humanly possible and with it is going to get rid of a lot of headaches and is going to eliminate a lot of frustration and get you up get back for you a lot of your time.
Now real quick. Let's let's just take a look at what I'm not saying. First of all, I'm not saying that your code base can be a hundred percent predictable. I'm not saying you won't ever have to do any digging to kind of find what you're looking for, right? That's simply not possible. I'm also not saying that your code base can be a hundred percent understood as a whole. In fact, most applications or at least a lot of very large applications are just simply too complex to be able to hold the whole thing in your head at one time. And therefore a code base being predictable isn't necessarily about being able to understand the whole thing at one time. To me predictability is really more about being able to predict where a certain piece in that code base fits in and really be able to only focus on that one piece at a time without having to think about the rest. In fact, I think that's a measure of a really good code base.
Alright. So how do we accomplish predictability? That's the question. Isn't it? Well, once again, if I may be so bold, I'm going to try to answer it in a single word. That word is standards. Why standards? Well, because really, this is how you make anything predictable, right? I can know with a pretty much 100 percent surety that when I go to change the sheets on my son's bed tonight, that the sheets I get out of the closet will fit because there is a standard sizing system and it's just made that way with a standard. Now I may be I may get the wrong size sheets out of the closet for my bed instead of his, but we've been there.
3. Vue.js Community Standards
Standards are the single largest predictor of a maintainable code base. There are four sources of standards in the Vue.js community: the Vue.js Style Guide, scaffolding generated by Vue.cli, official Vue.js libraries, and popular component frameworks. These sources provide shared standards, making it easier to interact with others and onboard new team members. Consider using existing solutions before creating your own, as they come with built-in tests, great documentation, and established standards.
But that's on me. That's not the standards fault. All right. Now, once again, I'm not saying standards is a silver bullet. It's not something that's going to solve all your development woes. But I think it's the single largest predictor of a maintainable code base if you're following the standards.
So that begs the question, what kind of standards exist for the view community at large? What are those standards out there that we can all share together and all know about whether we're working on, you know, by ourselves, on a small team or anywhere across the world? And in my eyes, there are four sources of standards across the Vue.js community. The first is the Vue.js Style Guide. And probably the most obvious, because its literal purpose is to provide a set of standards for us all. The next is the scaffolding generated by the Vue.cli. Now I'm not getting into Vue.cli or Vite here because really I prefer Vite, but I'm really just talking about that file structure that we're all used to seeing. Another source is the official Vue.js libraries. And those are all the libraries listed on the official Vue documentation website under the official projects piece there. And then lastly, and yes, admittedly, maybe a little bit more loosely, we have the most popular component, frameworks. Things such as Vue. Defy or Quasar or Bootstrap Vue.
So let's first of all, dive a little deeper into those last two items. That is, the official component, the official and component libraries. Admittedly their primary purpose is functionality. However, as a side effect of them being so widely used, they also provide shared standards. What do I mean by that? Well, take VueRouter, for instance. If you end up using VueRouter as your routing solution for your Vue.js project, you're not just opting in to a package, you're really opting in to a community of people who use the exact same package. And therefore, you're able to interact with others all across the world who are knowledgeable and familiar with that package. So that's part of what these official libraries and these component libraries provide for us is this set of standards to follow. VueX embraces this by saying on its official website that it's a state management pattern plus library. It understands the importance of having a pattern, a standard to follow. Now, what is my point in saying this? Some of this may seem a little bit obvious, but my point is you should really consider using the existing solution before trying to roll your own or go with some other solution. If there's already a solution out there to meet your needs, go and try to use it unless you have a really good reason not to, because not only does that solution come with built in tests, not only does it come with great documentation, but it also comes with standards, standards that people beyond your team are aware of, and that'll make onboarding new people just that much easier. Now this applies, I think, to all the component libraries as well, just on a little bit looser level, but the same idea.
4. Component Standards in Vue.js
Now this applies to all component libraries as well. The structure provided by the Vue CLI is a familiar standard that we should not mess with, unless there's a good reason. The Vue.js Style Guide provides component standards that make code more predictable. Some of these standards include using dedicated single file components, naming components in Pascal case, and prefixing base components with app or base. It also suggests using multi-worded names to prevent clashing with HTML elements, prefixing single instance components with the word the, and prefixing tightly coupled child components with the component name they're coupled to. Lastly, components should begin with the most general term and end with the most specific for easy grouping in IDEs.
Now this applies, I think, to all the component libraries as well, just on a little bit looser level, but the same idea.
Alright, that next standard is the structure provided by the Vue CLI, and I really don't have a whole lot to say about this, other than it's something we're all familiar with, so let's not mess with it, unless we have a really good reason to.
Alright, if we drill down now into the components directory and if we look in the Vue.js Style Guide, you'll see that we have some component standards described for us in the Style Guide that will really go a long way to making our code more predictable.
So let's take a look at a few of those standards today. The first one mentioned in the Style Guide is that we really should be using dedicated single file components. There's really no good reason, unless you're not using a build tool, to not just put all your components in a dedicated Vue file.
Also, your single file components should be named in Pascal case. Your base components should be prefixed with either app or base. And this just kind of groups them all together in the file structure and provides that standard where other people can look at the app... or excuse me, look at the component and say, oh, that's kind of an app-wide reusable component. I know exactly when and where I can use that. And I actually prefer to use app all the time because it starts with an A and is typically going to group all of those and put all of those at the very top of my components directory.
Alright, another thing in the Vue.js style guide is to use multi-worded names for your components. And this is really more than just a stylistic thing. This is in order to prevent clashing with future or existing HTML elements as they are by definition always a single word.
Another standard in the Vue.js style guide is to prefix all your single instance components with the word the. That is components that will only ever be used once per page. Things like the header or the sidebar. Once again, that predictability makes a new developer or someone brand new to the project know instantly what these components are about.
It also suggests to prefix tightly coupled child components with the component name that they're tightly coupled to. For instance, you could have a to do list and then items within that to do list. And so you would have a to do list component and a to do list item component. Likewise, you could have a job form and then a special location map field on that form. And therefore that component would be called job form location map field.
All right, sometimes, yes, this can get a little bit wordy, but it really groups them together and helps people know that they are coupled and they cannot be used one without the other. And then lastly, begin with the most general term within your component and end with the most specific. This just groups things together once again. And when you're searching for them in your IDEs, quick find or whatever, you can kind of see everything grouped together in one fail search. So, for instance, you've got the search widget, you've got the search widget input, and lastly the search widget results list.
All right, the Vue.js Style Guide actually has a whole lot of other really valuable things in it.
5. Personal and Team Standards
I encourage you to check out the Vue.js Style Guide and utilize the official ESLint plugin for real-time recommendations. Additionally, I recommend establishing personal or team-wide standards to complement the community-wide ones. One such recommendation is a flat component directory, which offers benefits like quick navigation and improved searchability. Although I haven't personally used this structure, I believe it can greatly enhance the development process.
But I won't regurgitate them all for you here today. But I do really encourage you go check it out. It was actually quite a long ways into my time developing with Vue before I even realized that the Vue.js Style Guide existed. And if I'd been utilizing it earlier in my career, earlier in my Vue development, then I probably would have saved myself some headache and some troubles when it came to communicating and coding with my teammates about Vue.
All right. So that does it for the community wide standards that we have available to us. But I think I'd really be remiss if I didn't recommend a few personal or team wide standards that I've found useful. I think these are just absolutely necessary because that the community wide standards simply aren't comprehensive enough to cover all our needs. Now, I'm not saying that's the community's fault. There are plenty of standards out there. We just have a lot of different applications, a lot of different ways of doing things. And that's just kind of the way the development world goes. But I really think it's essential that for our own personal development or for our teams that we we craft some standards for ourselves. It's really going to make your development process much smoother.
All right. So my first recommendation for your personal or team standard is a flat component directory. Now, I know some of you might look at this and think it might seem a little crazy, but just hear me out and don't tune out just yet. I think there are a number of different benefits that the flat component directory provides. The first one is that you can quickly navigate from the review dev tools to the component file. You just look at the component name and the dev tools and then you can go directly to it in your file structure without having to surf through different directories and and browse through different directories and all this. They're just all in that flat components directory listed alphabetically for you. It really also encourages navigation with your ideas, quick find feature, that is, because navigating through that long list becomes a little bit more difficult. It really makes you and forces you to try and do the search thing. And if you're naming your components correctly, as the style guide suggests, all your grouping that would normally be done with folders anyway will kind of come out of the box for you. And there's a few other benefits to it that I just don't have time to go over today, but I'm going to be sharing these slides on Twitter after the talk. So if you want to look at that more, you can at that point.
Now, I actually have a little bit of a confession to me, and that is I've never actually used the flat component structure in my own projects and in the projects that I've done at work.
6. Alternative: Almost Flat Component Structure
I've heard from some smart folks that an almost flat component structure can work well for large apps. While I haven't used it personally, I'll show you an alternative that I have used. It's a compromise between the flat component structure and domain-driven design, where page-specific components are stored in a partial directory. This approach has worked out nicely for me.
But I wanted to share it with you guys because I've heard it on the basis of some really smart folks that this really can work well, even for apps at a very large size. But since it's not something that I've used personally myself, I can't 100 percent recommend it and want to show you the alternative that I have used. But it's very close and I'll call it today an almost flat component structure. And the reason I'll call it an almost flat component structure is because our components directory actually still is flat. My only difference is that for components that are page specific, I like to store those in a partial directory with my page components. So, for example, as you can see in the screenshot, there's the views directory and I have a number of different pages that have to do with the client's resource of my application. And within that client's folder are my pages and directory called Partials. Now, what lives in partials here are components that go only on those client pages. They're not full pages within them within and of themselves, but they are just pieces of those client pages. And I find this works out really well as kind of a compromise between the flag component structure and domain driven design. It's kind of an in-between. It works out nicely for me.
7. Standardized Route Naming Convention
The next standard I recommend is a standardized route naming convention. It works great for Laravel and can be adopted for the Vue community. Most CRUD applications have four typical needs for a resource: listing, creating, showing, and editing. By following this naming convention, your routes become predictable.
All right, the next the next standard that I want to recommend that you utilize in your personal projects or your team projects is a standardized route naming convention. And in fact, we kind of saw that in action in the screenshot we put up just a minute ago. Here we see clients create, clients edit, clients index and clients show. If you're familiar with Laravel, this probably looks really familiar to you because it's a standard that they adhere to. And it works great for Laravel so why not adopt it for the Vue community?
Most applications, most CRUD applications have four typical needs for a particular resource. For instance, you would have to have a way to list all of them, a way to create one of them, a way to show a single one of them, and a way to edit a single one of them. And of course, a way to delete them as well. But that typically doesn't need a whole page. And so you would see what a resource called users would look like with this standardized route naming convention for a CRUD application. And I'm not going to go through them all because we just don't have the time to, but this really works well and makes your routes very predictable.
8. Miscellaneous Tips for Large Scale Applications
Wrap your third party libraries in components to easily switch out dependencies and extend functionality. Extend your HTTP class with caching or create wrapper components for third party icons. Wrap rest APIs in a simple SDK to eliminate typos and provide autocomplete. Auto register base components globally to simplify importing and registering.
All right, I want to go now a little bit beyond predictability and talk about some other miscellaneous tips for large scale applications.
My first tip here is wrap your third party libraries in components. What do I mean by that? Well, let's take a look at this example. Let's say you're using Axios as your HTTP client, and what I would recommend you do is actually wrap Axios in a maybe more generically named class such as HTTP, and then actually just use Axios under the hood to do the actual grunt work. Now, why in the world would I do this, like unless I'm being paid by the line? Right? It seems like it just creates a little extra friction, a little extra work. But there are a few benefits. The first is that if for some reason you ever have to switch out Axios for some other HTTP solution, you only have to do it in the one place. For like in this example, I've switched out Axios with Fetch. I didn't have to go throughout my entire codebase and switch things out, but rather I just had to target that HTTP class and the rest of the codebase continues using the HTTP class as normal. In fact, the people who are using that HTTP class throughout the rest of the codebase, they don't really have to know that the underlying dependency changed. They just keep using the same interface for that class as they've been used to using. Another benefit of it to me is that it really exposes ways to kind of expand the functionality of your utility classes. For instance, here I've kind of built in a way to alert a user or perform some kind of action whenever an HTTP request fails from Fetch. Now, alert obviously maybe isn't the best solution, isn't the best user friendly thing, but you get the idea. Now, of course, with Axios, there are also certain hooks you can hook into to do similar things, but to me they're just not as obvious. And for some third party libraries, those hooks simply may not exist. And so if you wrap them, the ability to extend and augment your third party libraries really becomes a lot more clear and a clean path for how to do that.
And this is just one more example of how you could do the same thing by extending your HTTP class with some caching. All right. So not only can you do that with libraries, though, things that are more functional in nature, but you can actually even do it with third party components. So, for instance, I could create a wrapper component called app icon, and we've called it app icon because of standards. Right. And so what this app icon does is actually provides a singular interface for working with multiple types of third party icons, in this case, Phone Awesome and Material Design icons.
My next step for you guys is to interact with rest APIs, with SDKs, maybe your service already provides an SDK, and if it does, then great, use it. But if all it provides is an API endpoint to hit, I encourage you wrap that wrap that API in a simple SDK of your own. And that could be an SDK you end up using just for that project, or it's something you could even share between multiple projects. But it really helps you eliminate the opportunity for typos and gives you something a little bit smarter to work with, something like a class with a method on it that your IDE can autocomplete for you. Plus, should the rest API change sometime down the road, you only have to update your SDK and the rest of your code base can remain untouched. Also, auto register base components, they need to be available globally anyway, so you might as well go ahead and auto register them with a simple piece of code such as this, and you don't even have to think about importing and registering them yourself.
9. Auto Registering Components and Testing
Auto register base components globally, and don't forget to do thorough testing. The recommended library for testing Vue.js components is Vue.testing library. In conclusion, Vue School offers various business services, including development, consulting, and team training. They also provide the Vue.js 3 master class and other courses to help you become an expert with Vue.
Also, auto register base components, they need to be available globally anyway, so you might as well go ahead and auto register them with a simple piece of code such as this, and you don't even have to think about importing and registering them yourself.
And then lastly, just do your testing. I know there's a lot of times that we just don't feel like doing it and it's not the most exciting thing in the world, but for your large scale applications, I promise you, it's better to do the work up front than to have to deal with the bugs and the regression issues down the road. On a personal level, yes, sometimes testing can be frustrating, but I have never, ever regretted doing or creating a test. There have been plenty of times where I have regretted not creating a test.
And also, just to let you guys know, the recommended library now for testing your Vue.js components is the Vue.testing library, not Vue.testutils. Vue.testing library is actually built on top of Vue.testutils, but it gives you just a little bit higher abstraction to make writing your test that much easier.
All right, that wraps up my talk on patterns for large scale Vue.js applications. But maybe you're in the middle of writing your own Vue.js application and you could use a little help. Well, over at Vue School, we'd be happy to lend a hand. You see, we offer a number of business services, including development, consulting and team training in the form of educational videos, as well as live workshops. So if you're interested in any of these services, reach out to us at team at VueSchool.io and we'd be happy to help.
Also, if you want to build your very own real world Vue.js application, you should check out the Vue.js 3 master class in it. Alex and I teach the essentials, things like Vue Router and single file components, but also do deeper dives into more complex topics like state management with Vuex, SEO, and more. Plus, if you sign up for our subscription service, you get access to the Vue.js 3 master class plus access to a number of other great courses that will teach you how to be an expert with Vue. Plus, there's a number of these courses that are free, so you really have no excuse to not go and just check them out today.