4 best practices for developing large-scale Vue projects

As you know, Vue.js is a JavaScript-based framework that has grown rapidly in popularity in recent years.



There are many reasons for Vue's rise in popularity. This includes the simplicity of the framework, the ease of its integration into existing projects, the convenience of working with it, and not too strong restrictions imposed on Vue applications. All of this also helps Vue compete with Angular and React. In fact, it feels like Vue is, in many ways, on par with other popular frameworks and libraries.



I decided to find out what they write about the shortcomings of Vue. While looking for relevant materials, I noticed that everywhere they say that Vue is not good enough for developing large-scale projects. Knowing Vue, I can confidently say that this is not true. In this post, I want to bring to your attention 4 detailed guidelines for developing large-scale Vue projects.











1. Use Vue slots to make your code clearer



When setting up component relationships, the parent-child model is most often used. But in some situations, such a model may be far from the most successful. Imagine you have a single parent component that hosts a large number of child components. This means that you will have to use a large number of input parameters (props) and generate many events to establish the interaction of components. In such conditions, the code will get messy very quickly. These are the situations that developers of large-scale projects face. But Vue has mechanisms designed specifically to deal with these kinds of problems.



We're talking about slots. They are used to provide an alternative way of representing parent-child relationships. Slots, namely elements <slot>, give the developer the ability to reorganize the code. Here's a simple example of using a slot:



<div class="demo-content">
   <slot></slot>
</div>


When such a component is rendered, the tag in it <slot></slot>will be replaced with the content of the tag <demo-content>:



<demo-content>
  <h2><font color="#3AC1EF">Hi!</font></h2>
  <class-name name="Welcome to Vue!"></class-name>
</demo-content>


There are many varieties of slots that can be used in Vue projects. The most important thing you need to know about slots is that their use can have a huge impact on a growing project. They keep your project code in good shape and help you create clean code.



2. Create independent components and reuse them



When designing components, follow the FIRST principle by making components Focused, Independent, Reusable, Small, and Testable.



In fact, the secret to designing "large" systems effectively is not to try to build those systems in the first place. Instead, these systems need to be assembled from smaller pieces that solve highly specialized problems. This makes it easier to assess how the smaller parts of the systems fit into their β€œlarger” goals.

Eddie Osmani



You can use specialized systems like Bit to create and manage components . Here's the stuff about it.



3. Keep your Vuex store well organized



Vuex is a Vue application state management pattern and library. With Vuex, you can organize a centralized data store for all application components. I've seen comments about Vuex that say that Vuex limits developers' ability to structure a project and prevents them from doing what they need to do. I do not agree with such statements. Vuex actually helps developers who follow a set of principles to structure their projects, making them better organized.



Before I talk about these principles, I would like to talk about 4 main components of Vuex repositories that anyone who wants to use such repositories effectively needs to know about. If you are familiar with these components, it means that you can easily structure your Vuex store and improve project organization. Here is a short description:



  • States: Used to store application data.
  • Getters: used to organize access to state objects outside of storage.
  • Mutations: needed to modify state objects.
  • Actions: Used to apply mutations.


Assuming you are familiar with these components, let's talk about the above principles:



  1. The state of the application layer needs to be managed centrally by storing it in a repository.
  2. State changes must always be made using mutations.
  3. Asynchronous logic must be encapsulated; it must only act on state through actions.


If you can adhere to these 3 principles, it means that you will be able to structure the project well. If, in the course of project growth, you decide that the code of the corresponding Vuex components needs to be placed in different files, you can do it. Below is an example of a project structure using Vuex:



β”œβ”€β”€ index.html
β”œβ”€β”€ main.js
β”œβ”€β”€ api
β”œβ”€β”€ components
└── store
    β”œβ”€β”€ index.js          
    β”œβ”€β”€ actions.js
    β”œβ”€β”€ mutations.js
    β””── modules


▍Vuex modular storage organization



In this article we are talking about large-scale projects. From such projects, you can expect the files used in them to be very large and complex. Programmers creating such projects need storage management mechanisms that reflect their needs. At the same time, the storage structure should not be unnecessarily complicated. Therefore, it is recommended that you organize your Vuex stores in a modular fashion, customizing them according to your vision of the best structure for such stores. There is no definite way to divide storage into modules. Some developers take a design capability-based approach, and some take a data model approach. The final decision on dividing the storage into modules is made by the programmer responsible for the project.Reasonably structured storage has a positive impact on the usability of a project over the long term.



Here's an example of a modular approach to structuring storage:



store/
   β”œβ”€β”€ index.js 
   β””── modules/
       β”œβ”€β”€ module1.store.js
       β”œβ”€β”€ module2.store.js
       β”œβ”€β”€ module3.store.js
       β”œβ”€β”€ module4.store.js
       β””── module5.store.js


▍Using helper methods



Above, I talked about 4 components used in Vuex repositories. Consider a situation when you need to access states and work with getters, when you need to call actions and mutations in components. In such cases, you do not need to create many methods or computed properties. You can simply use a helper method ( mapState, mapGetters, mapMutationsand mapActions), the use of which would avoid unduly increasing the code volume. Let's talk about using these helper methods.



▍mapState



If a component needs to access multiple storage properties or multiple getters, this means that we can use a helper method mapStateto generate a getter function. This saves us from having to write relatively large amounts of code.



import { mapState } from 'vuex'
export default {
  computed: mapState({
    count: state => state.count,
    countAlias: 'count',
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })
}


▍mapGetters



The helper method is mapGettersused to configure the mapping of storage getters to local computed properties.



import { mapGetters } from 'vuex'
export default {
  computed: {
    ...mapGetters([
      'count1',
      'getter1',
    ])
  }
}


▍mapMutations



The helper method is mapMutationsused in components to apply mutations. It defines the correspondence between component methods and calls store.commit. In addition, this method can be used to transfer some data to the storage.



import { mapMutations } from 'vuex'
export default {
  methods: {
    ...mapMutations({
      cal: 'calculate' //  `this.cal()`  `this.$store.commit('calculate')`
    })
  }
}


▍mapActions



A helper method mapActionsis used in components to dispatch actions. It defines the correspondence between component methods and calls store.dispatch.



import { mapActions } from 'vuex'
export default {
  methods: {
    ...mapActions({
      cal: 'calculate' //  `this.cal()`  `this.$store.dispatch('calculate')`
    })
  }
}


4. Don't forget about unit tests



Testing is another important aspect of any project. Developers should test what they create, regardless of the importance and size of the projects. This is especially true in large-scale projects that have hundreds or even thousands of small functions. Our task is to test each of them. Unit tests help solve this problem. They allow the programmer to test individual modules of code. Such tests not only allow you to identify and eliminate errors. They also increase the level of confidence of the programmer or team of programmers in the correctness of their actions when changes are made to the existing code. When, over time, the project grows, developers, thanks to the use of unit tests, can safely add new features to it and at the same time not be afraid thatthat innovations will disrupt the work of existing mechanisms. All you need to do is follow the practice of writing unit tests from the very beginning of the project.



If we talk about unit tests used in projects based on Vue, then we can say that such tests are almost identical to those used in projects based on other frameworks and libraries. Namely, Jest , Karma or Mocha work well with Vue . But, no matter which framework you choose to create your tests, there are some general guidelines to keep in mind when developing unit tests:



  • If the test fails, it should display clear error messages.
  • It is recommended to use good assertion libraries when creating tests. (For example, the mechanisms for generating claims are built into Jest, and with Mocha, the Chai library is used).
  • Unit tests should cover all Vue components.


If you follow these recommendations from the very beginning of the project, it, as the project grows, will greatly reduce the time spent on debugging the code and on its manual testing.



Vue projects, in addition to unit testing, can be subjected to end-to-end and integration testing. The situation here, as in the case of unit tests, is also very similar to the situation with other frameworks and libraries. Therefore, it is recommended to include in projects and similar tests. Typically, the routing part of a project is not tested with unit tests. End-to-end testing is used here. Testing the Vue store is the biggest challenge. It is recommended to use integration tests to test it, since it is considered a waste of time to test states, actions or getters separately.



Outcome



After reviewing the technical capabilities of Vue.js in this post, I have strengthened my belief that this framework is suitable for developing large-scale projects. With its help, as with other frameworks and libraries, you can create such projects and manage them, keeping them in good condition.



Do you think Vue is suitable for developing large-scale projects?






All Articles