
Best Practices Programming in Vue.js with async and await
Master async and await in Vue.js to build high-performance, scalable, and responsive applications. This article covers best practices and advanced tec...
Sep 10, 2024
In today’s fast-paced tech environment, creating high-performance applications with Vue.js is crucial for smooth user experiences and scalability. Vue.js offers powerful tools, but advanced techniques can significantly enhance performance, security, and scalability.
Pinia is a modern state management tool for Vue.js, simpler and more flexible than Vuex. To optimize Pinia for large applications, follow these tips:
Modular Store: Divide your store into modules for better organization and scalability.
import { defineStore } from 'pinia';
export const useCartStore = defineStore('cart', {
state: () => ({ items: [] }),
actions: {
addItem(item) { this.items.push(item); },
removeItem(id) { this.items = this.items.filter(item => item.id !== id); }
}
});
// store/modules/products.js
import { defineStore } from 'pinia';
export const useProductsStore = defineStore('products', {
state: () => ({ products: [] }),
actions: {
async fetchProducts() {
const response = await axiosInstance.get('/products');
this.products = response.data;
}
}
});
Use Getters for Derived State: Getters in Pinia are similar to computed properties and can cache results.
export const useCartStore = defineStore('cart', {
state: () => ({ items: [] }),
getters: {
totalPrice: (state) => {
return state.items.reduce((total, item) => total + item.price * item.quantity, 0);
},
itemCount: (state) => {
return state.items.length;
}
}
});
Debounce Actions: For actions triggered by user input, use debounce to avoid unnecessary calls.
// In a component
<template>
<input v-model="searchQuery" @input="onInput" placeholder="Search products..." />
</template>
<script>
import { ref } from 'vue';
import { useProductsStore } from '@/store/modules/products';
import debounce from 'lodash/debounce';
export default {
setup() {
const searchQuery = ref('');
const productsStore = useProductsStore();
const onInput = debounce(() => {
productsStore.searchProducts(searchQuery.value);
}, 300);
return {
searchQuery,
onInput
};
}
};
</script>
Centralized Axios Setup: Create a central instance of Axios for easier management.
import axios from 'axios';
const axiosInstance = axios.create({
baseURL: 'https://api.example.com'
});
axiosInstance.interceptors.response.use(
response => response,
error => {
if (error.response.status === 401) {
// Handle unauthorized error
}
return Promise.reject(error);
}
);
export default axiosInstance;
Lazy Loading Data with Axios: Use Axios to load data incrementally.
import axiosInstance from '@/utils/axiosInstance';
import { defineStore } from 'pinia';
export const useProductsStore = defineStore('products', {
state: () => ({
products: [],
page: 1
}),
actions: {
async loadMoreProducts() {
try {
const response = await axiosInstance.get(`/products?page=${this.page}`);
this.products.push(...response.data);
this.page += 1;
} catch (error) {
console.error('Error fetching products:', error);
}
}
}
});
Using Axios in a Component
<script>
import { onMounted } from 'vue';
import { useProductsStore } from '@/store/modules/products';
export default {
setup() {
const productsStore = useProductsStore();
onMounted(() => {
productsStore.loadMoreProducts();
});
const onScroll = () => {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight) {
productsStore.loadMoreProducts();
}
};
window.addEventListener('scroll', onScroll);
return {
products: productsStore.products
};
}
};
</script>
Using functional components for stateless rendering can improve performance as they are simpler and faster to render.
<template functional>
<div>{{ props.message }}</div>
</template>
<script>
export default {
props: ['message']
};
</script>
Using Vue’s built-in
Additionally, dynamic imports allow for lazy loading of components, reducing the initial bundle size and speeding up the loading time of your application.
<template>
<keep-alive>
<router-view></router-view>
</keep-alive>
</template>
Dynamic imports enable the application to load components only when needed, which reduces the initial load time, improving performance for large-scale applications.
const routes = [
{ path: '/about', component: () => import('@/views/About.vue') },
{ path: '/contact', component: () => import('@/views/Contact.vue') },
// Additional routes
];
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
When working with user input and APIs, it is essential to sanitize and secure the data to avoid vulnerabilities such as XSS and CSRF attacks.
Below are some best practices for securing Vue.js applications.
Sanitize User Input: Use libraries like DOMPurify to clean up HTML and prevent malicious scripts.
import DOMPurify from 'dompurify';
export default {
methods: {
sanitizeInput(input) {
return DOMPurify.sanitize(input);
}
}
};
Avoid using v-html: Directly rendering raw HTML can expose your app to XSS attacks. Always sanitize the content.
<div v-html="sanitizeInput(untrustedHTML)"></div>
CSRF Protection: When sending requests to an API, ensure you use CSRF tokens for verification to prevent unauthorized requests.
Vue Devtools is a powerful tool that simplifies debugging by letting you inspect your application's state, mutations, and actions. Use it to track the state of Pinia stores as well.
Profiling performance in your browser’s dev tools helps identify slow components and bottlenecks in rendering, allowing for optimization.
Vue Devtools: Inspect the state of your application, including components, Vuex/Pinia state, and events.
Performance Tab: Use the Performance tab in your browser’s developer tools to profile your app and monitor performance bottlenecks.
For large-scale applications, containerization and server-side rendering (SSR) can improve scalability and performance.
Docker and Kubernetes help manage scaling and load balancing, while SSR ensures faster initial loading and better SEO.
Server-Side Rendering (SSR): Use SSR for improved SEO and faster initial loading of your Vue.js application.
import { createSSRApp } from 'vue';
import { renderToString } from '@vue/server-renderer';
import App from './App.vue';
const app = createSSRApp(App);
renderToString(app).then(html => {
// Send HTML to client
});
Scaling with Docker and Kubernetes: Containerize your application with Docker and use Kubernetes for managing load balancing and scaling.
apiVersion: apps/v1
kind: Deployment
metadata:
name: vue-app
spec:
replicas: 3
selector:
matchLabels:
app: vue-app
template:
metadata:
labels:
app: vue-app
spec:
containers:
- name: vue-container
image: vue-app:latest
ports:
- containerPort: 80
Building high-performance Vue.js applications requires mastering advanced techniques in state management, data fetching, security, and scaling.
By implementing these best practices, you can ensure your applications are optimized for performance, security, and scalability, providing users with a seamless experience.
Get in touch with PosterumSoft and discover how we can help you optimize your frontend development and scale your business.
Follow us on LinkedIn: linkedin.com
Follow us on X: x.com
Follow us on Medium: medium.com
Our Upwork profile: upwork.com
Master async and await in Vue.js to build high-performance, scalable, and responsive applications. This article covers best practices and advanced tec...
Financial technology (fintech) continues to evolve rapidly, transforming how both businesses and individuals manage finances...