Vue best practices 2023

Whether you’re running a developer team or hiring a developer, you need to follow good practices to avoid technical debts. VueJS is no different than other front-end frameworks in that regard.

To get you started, we compiled a curated list of best practices we glanned from repositories, official documentation, and personal experience. Hope you enjoy it!

VueJS Is Good For Business

Vue.js is an excellent choice of Javascript framework for businesses building web applications. It has a simple template-like syntax that’s easy to learn:

<script setup>
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
  <button @click="count++">You clicked me {{ count }} times.</button>
</template>

The smooth learning curve combined with officially maintained packages for routing, state management, and other goodies makes it great for your team from a developer experience perspective.

The framework has a vibrant and supportive community resulting in a thriving ecosystem packed with third-party libraries, tools, and services to increase developer productivity. Its popularity attracts more and more developers, so you won’t run into trouble hiring people to contribute to your projects. [stars, downloads, costs]

From an end-user’s perspective, Vue.js delivers exceptional performance compared to similar web frameworks―your web applications will load quickly, even at scale.

a lighthouse test

That being said, it's important to pay attention to a few elements to make the most of it, and this is why we're here! Without further ado, let's get into it.

1. Dealing with APIs

To build a full-blown web app, you’ll need to interact with your backend via APIs. Now, bad API management can result in slow applications―or worse, security threats―so you’ll need to follow a few best practices to optimize user experience:

  • Leverage state management - Managing your application's state to avoid redundant API calls while ensuring your components use up-to-date data is key. Vue offers basic state management features to share data between components, but you’ll need a full-blown state management library in some cases like []
  • Wrap your API calls - Instead of using SDKs or the fetch method directly, always wrap your API calls in a service layer. This allows you to easily switch API providers and abstract how you handle API responses and errors. Additionally, make sure to throttle or debounce your API calls in the wrapper.
// api.js

function getPosts() {
  return fetch('https://jsonplaceholder.typicode.com/posts')
    .then(response => response.json())
    .then(json => json)
    .catch(error => console.log(error))
}

const debouncedGetPosts = debounce(getPosts, 500)

export default {
  getPosts: debouncedGetPosts
}
  • Don’t forget authentication & authorization - Security is a critical aspect when dealing with APIs: only authorized users should access certain parts of your application and perform specific actions. JWT and other access tokens should never be stored in cookies or localStorage, and use vulnerability scanners to make sure you don’t leave sensitive information for everyone to see.
  • GraphQL Integration - GraphQL allows API clients to specify the exact data they need to avoid over-fetching or under-fetching data. For data-intensive applications, GraphQL gives a great boost to your UI.

Additionally, never trust user input. Regardless of the method used to interact with APIs, always validate and sanitize user-provided data on the backend―serverless functions will do just fine―to prevent potential security breaches.

2. Project structure

Organizing your Vue.js project and files in a well-structured manner helps maintain a readable and maintainable codebase.

  • Clear folder organization - Creating dedicated folders for various parts of your application can lead to better organization and clarity. By separating concerns into different folders, you can quickly identify and navigate to specific files when working on different features or fixing bugs. When structuring your Vue.js project, consider organizing your files based on the MVC architecture. Group related components, views, and data logic together, making it easier to locate and manage different parts of your application. For example:
├── src
│   ├── components // reusable components
|    ├── Login
│   ├── services // API requests
|    ├── Auth
│   ├── views // top-level views or page components
│   ├── store // Vuex store-related files
│   ├── utils // utility functions or helper modules
├── public
│   ├── assets // static assets like images, fonts, and stylesheets
  • Organize components hierarchically - per page or group child components in a folder
  • Use clear naming conventions - To prevent naming collisions and ensure a well-organized codebase, consider using meaningful names for modules and components. For example,

Another crucial aspect of maintaining a well-organized project structure is proper documentation, so write down agreed-upon conventions in your contribution guide. Even though naming conventions are obvious to find from a glance at the repository, having clear guidelines accompanied by short explanations always helps.

3. Testing

Frontend testing isn’t as straightforward as backend testing, but new tools make it easier than ever:

  • Unit and functional tests for API calls - Write tests covering your service layer to quickly identify and fix issues and make the code easier to maintain overall. Unit tests also provide a safety net during refactoring if you want to change API providers someday.
import assert from 'assert'
import  { getPosts }  from '../src/services/api.js'

describe('Array', () => {
  describe('#getPosts()', () => {
    it('should return all the posts', async function () {
      const posts = await getPosts()
      assert.equal(posts.length, 5);
    });
  });
});

  • Component-based testing with Storybook - Component-based testing involves testing Vue components in isolation. This type of testing ensures that components render as expected, respond correctly to user interactions, and interact with other components as intended. A tool like Storybook also makes it easier to reuse components across projects or quickly test out new ideas and variations.
  • End-to-end tests with Puppeteer - With Puppeteer for headless browser automation, E2E tests simulating user interactions across multiple components and pages can be conducted in a real browser environment without the need for a graphical interface. This ensures that the application works as expected from the user's perspective, catching bugs that might only surface during integration. This is especially useful to make sure the web app works on different screen resolutions.

Make sure to run your tests with each code change or pull request. CI/CD service providers like Github Actions or Vercel often allow you to run your test command and see the result.

4. Routing

Unoptimized routing, going from one view to another, will decrease the performance of your UI.

  • Leverage code splitting - Use Vue’s code splitting feature to lazy load route components and libraries and increase performance.
import { defineAsyncComponent } from 'vue'

const Foo = defineAsyncComponent(() => import('./Foo.vue'))

function loadLazy() {
  return import('./lazy.js')
}
  • Multi-thread with Partytown - Partytown is a library that offsets main thread processing to web workers to increase performance, allowing your routes to load faster when they rely on third-party libraries. Simply add type="text/partytown" to your script tags and you’re good to go!
<script type="text/partytown">...</script>

Vue Router is Vue’s official routing library, so no need to reinvent the wheel here.

const Home = { template: '<div>Home</div>' }
const About = { template: '<div>About</div>' }

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
]

const router = VueRouter.createRouter({
  history: VueRouter.createWebHashHistory(),
  routes
})

const app = Vue.createApp({})

app.use(router)

app.mount('#app')

5. SSG vs SSR vs SPA

Vue proposes different rendering methods: SSR (server-side rendering), SSG (static site generation), and CSR (client-side rendering, or Single Page Application).

  • Use SSR if a public-facing webpage requires dynamic data that is frequently updated. SSR provides a better user experience by showing content that is always up-to-date while helping with SEO. Example: a forum, a community board, a login page using CSRF tokens.
  • Use SSG if your webpage does not require frequent updates and can be pre-rendered. SSG provides faster load times as webpages are served as static files. Example: a blog post, a landing page.
  • Use SPA if your webpage displays frequent updates and real-time data. A SPA provides a smoother user experience as the web application does not need to reload on each page view, but it can be more difficult for search engines to crawl results in slower initial load times. Example: a private dashboard, a user account, or any private webpage.

A typical situation we encounter with clients is the need to have website pages along the web app―about, contact, landing pages, etc. In this case, it’s better to ship two different Vue repositories: one for the website using SSG, and one for the web app using SSR and/or SPA.

VitePress is Vue’s official static site generator, but you can also use Nuxt to mix SSR and SSG, or Astro to leverage partial hydration (SSG with client-side hydration via island architecture).

6. Animation

Animations are part of modern web design, but businesses need to use them sparingly:

  • Less is more - Avoid overloading your UI with animations. They should enhance the user experience, not block users from doing what they need to do. Excessive and slow animations can result in lower conversion rates and higher bounce rates.
  • Load in less than 150 ms - Your loading time should always be less than 150 ms to feel instantaneous and increase user happiness. Keep that in mind when using transition animations.
  • Keep it simple - Simple animations are usually better at getting a point across. From an accessibility viewpoint, animations should never be necessary to access information or perform an action.

You can create animations with Vue using CSS classes, component state changes, and watchers. But basic animations also have community packages for you to try out.

7. Error handling

There is nothing more frustrating than a broken feature, and more so when the error message doesn’t help your user.

  • Use proper error logging - The console.log method should never be used for error handling. Instead, use dedicated logging software like Sentry or BugSnag to track and manage errors.
  • Throw exceptions - Always plan to throw exceptions in the eventuality of errors, and inform the user rather than silently failing. This ensures that issues are addressed promptly and adequately.
  • Abstract boilerplate code - Your app should always implement Vue’s errorHandler helper to catch propagating errors by logging them and displaying an alert to the end user. Similarly, your API calls should all be wrapped in try-catch blocks.

Depending on how you render your app, it’s also important to take into account situations where Javascript is disabled or when the network connection goes down.

8. Environment secrets

Secret leaks via phishing or credential theft are the most common security threats for startups.

  • Gitignore .env files - You can easily prevent accidental exposure of sensitive information by adding .env files to your .gitignore to avoid including them in your GitHub history for everyone on the team to see.
  • Avoid storing sensitive secrets - Never store critical secrets like API keys directly in your codebase, and ensure that debugging logs that might contain sensitive information are disabled in production environments.
  • Use a secret manager - A dedicated secret manager like Onboardbase or Doppler to securely store and manage sensitive data mitigates the risk of secret leaks. All your secrets are stored in a dedicated secure vault instead of being manually defined in your deployment environment.

Secret management can be stressful, but you’re good to go if you minimize the probability of human error.

Conclusion

Vue.js is excellent to build web applications with its simple syntax, exceptional performance, and supportive community. Using best practices as guidelines will help you maximize these benefits to deliver top-notch user experiences.

If you need VueJS development experts, consider hiring JAMStack Consulting. We have years of experience using a variety of front-end frameworks, including Vue and React / NextJS. We can not only adapt these best practices to your specific needs but also help your team adopt them, so don't hesitate to reach out!