Het Vue framework voor JavaScript is populair geworden voor het bouwen van gebruikersinterfaces en single-page applicaties (SPA’s). Om ervoor te zorgen dat je grote apps optimaal functioneren, heb je een goed begrip nodig van state management – het proces van het beheren en centraliseren van de reactieve gegevens (state) van een applicatie over meerdere componenten.

In Vue is state management lange tijd gebaseerd geweest op Vuex, een bibliotheek met een centrale opslag voor alle componenten van een applicatie. Recente ontwikkelingen in het Vue ecosysteem hebben echter geleid tot de opvolger van Vuex, Pinia.

Pinia biedt een meer lichtgewicht, modulaire en intuïtieve beheeraanpak. Het integreert naadloos met Vue’s reactiviteitssysteem en Composition API, waardoor het voor developers eenvoudig wordt om samen state te beheren en te benaderen op een schaalbare en onderhoudbare manier.

De achtergrond: Pinia vs Vuex

Als go-to bibliotheek voor state beheer in Vue applicaties, bood Vuex een gecentraliseerde opslag voor alle componenten van een applicatie. Met de vooruitgang van Vue vertegenwoordigt Pinia echter een modernere oplossing. Laten we eens kijken hoe het verschilt van Vuex.

  • API verschillen – Pinia’s Composition API biedt een meer fundamentele en intuïtieve API dan Vuex, waardoor het eenvoudiger is om de state van de applicatie te beheren. Bovendien lijkt de structuur erg op de Options API van Vue, die bekend is bij de meeste Vue ontwikkelaars.
  • Ondersteuning voor types – Historisch gezien hebben veel Vue ontwikkelaars geworsteld met de beperkte ondersteuning voor types van Vuex. Pinia is daarentegen een volledig getypeerde state management bibliotheek die deze zorgen wegneemt. De typeveiligheid helpt bij het voorkomen van potentiële runtime fouten, draagt bij aan de leesbaarheid van de code en vergemakkelijkt soepelere schaalbaarheid.
  • Reactiviteitssysteem – Beide bibliotheken maken gebruik van Vue’s reactiviteitssysteem, maar Pinia’s benadering sluit beter aan bij Vue 3’s Composition API. Hoewel de reactiviteit API krachtig is, kan het beheren van complexe states in grote applicaties een uitdaging zijn. Gelukkig verlicht Pinia’s eenvoudige en flexibele architectuur het gedoe van statesbeheer in je Vue 3 applicaties. Met Pinia’s store pattern kun je een store definiëren voor het beheren van een specifiek deel van de applicatie-state, het vereenvoudigen van de organisatie en het delen ervan over componenten.
  • Lichtgewicht karakter – Met slechts 1 KB integreert Pinia naadloos in je ontwikkelomgeving en het lichtgewicht karakter kan de prestaties en laadtijden van je applicaties verbeteren.

Zo zet je een Vue project op met Pinia

Om Pinia te integreren in een Vue project, initialiseer je je project met Vue CLI of Vite. Na het initialiseren van het project kun je Pinia installeren via npm of yarn als een afhankelijkheid.

  1. Maak een nieuw Vue project met Vue CLI of Vite. Volg vervolgens de aanwijzingen om je project in te stellen.
    // Using Vue CLI
    vue create my-vue-ap
    // Using Vite
    npm create vite@latest my-vue-app -- --template vue
  2. Verander je map naar de nieuw aangemaakte projectmap:
    cd my-vue-app
  3. Installeer Pinia als een dependency in je project.
    // Using npm
    npm install pinia
    // Using yarn
    yarn add pinia
  4. Importeer Pinia in je hoofdbestand (meestal main.js of main.ts) en vertel Vue om het te gebruiken:
    import { createApp } from 'vue';
    import { createPinia } from 'pinia';
    import App from './App.vue';
    
    const app = createApp(App);
    
    app.use(createPinia());
    app.mount('#app');

    Met Pinia geïnstalleerd en ingesteld in je Vue project, ben je klaar om stores te definiëren en te gebruiken voor statesbeheer.

Zo maak je een store in Pinia

De store is de ruggengraat van het state-beheer in je door Pinia aangedreven Vue applicatie. Het helpt je om applicatie-brede gegevens op een samenhangende en gecoördineerde manier te beheren. De store is waar je de gegevens definieert, opslaat en beheert die je wilt delen met de verschillende componenten van je applicatie.

Deze centralisatie is cruciaal, omdat het de state-veranderingen van je app structureert en organiseert, waardoor de gegevensstroom voorspelbaarder wordt en debuggen eenvoudiger wordt.

Bovendien doet een store in Pinia meer dan het opslaan van de state: Met de meegeleverde functionaliteiten van Pinia kun je de state bijwerken via acties en afgeleide states berekenen via getters. Deze ingebouwde mogelijkheden dragen bij aan een efficiëntere en beter onderhoudbare codebase.

Het volgende voorbeeld illustreert het maken van een basis Pinia store in het bestand src/store.js van een project.

import { defineStore } from 'pinia';
export const useStore = defineStore('main', {
    state: () => ({
        count: 0,
    }),
    actions: {
        increment() {
            this.count++;
        },
    },
    getters: {
        doubleCount: (state) => state.count * 2,
    },
});

Toegang tot store state in componenten

Vergeleken met Vuex is Pinia’s benadering van state-toegang en beheer intuïtiever, vooral als je bekend bent met Vue 3’s Composition API. Deze API is een set van verschillende die het mogelijk maken om reactieve en samenstelbare logica in je componenten op te nemen.

Bekijk de volgende code.

<template>
	<div>{{ store.count }}</div>
</template>

<script>>
import { useStore } from './store';

export default {
	setup() {
	const store = useStore();
		return { store };
	},
}
</script>

In het bovenstaande fragment bevat de tag <template> de gedefinieerde HTML opmaak van je component. Om de waarde van de properycount uit de Pinia store weer te geven, gebruik je Vue’s data binding syntaxis, uitgedrukt als {{ count }}.

De useStore functie biedt toegang tot de Pinia store, dus je importeert deze vanuit store.js met import { useStore } from './store';.

Een functie van Vue 3’s Composition API, de setup functie definieert de reactieve state en logica van je component. Binnen de functie roep je vervolgens useStore() aan om toegang te krijgen tot de Pinia store.

Vervolgens krijgt const count = store.count toegang tot de store’s count property, waardoor deze beschikbaar wordt in het component.

Tot slot geeft setup de count terug, zodat de template deze kan renderen. Het reactiviteitssysteem van Vue betekent dat de template van je component de waarde van count bijwerkt telkens als deze in de store verandert.

Hieronder zie je een screenshot van de uitvoer.

Screenshot van de Pinia Store Demo template geladen in een browser.
Screenshot van de Pinia Store Demo template geladen in een browser.

Dit voorbeeld illustreert de voordelen van Pinia:

  • Eenvoud – Pinia biedt directe toegang tot de state van de store zonder mapping-functies. In tegenstelling tot Vuex heb je mapState (of vergelijkbare helpers) nodig om dezelfde toegang te krijgen.
  • Directe toegang tot de store – Met Pinia heb je direct toegang tot state properties (zoals store.count), waardoor je code leesbaarder en begrijpelijker wordt. Ondertussen vereist Vuex vaak getters om zelfs fundamentele eigenschappen te benaderen, wat complexiteit toevoegt die de leesbaarheid vermindert.
  • Compositie API compatibiliteit – Zoals de setup methode laat zien, sluit Pinia’s integratie met de Compositie API bijzonder goed aan bij moderne Vue ontwikkeling, waardoor een meer uniforme codeerervaring ontstaat.

State wijzigen met Pinia

In Pinia pas je de state van een store aan met acties, die flexibeler zijn dan Vuex mutaties. Overweeg de volgende functie-call, die de property count van de state verhoogt:

store.increment(); // Increments the count

Een Vuex equivalent daarentegen bevat het definiëren van een mutatie naast ten minste één actie:

mutations: {
	increment(state) {
	state.count++;
	},
},
actions: {
	increment({ commit }) {
	commit('increment');
	},
}

De Pinia actie en de equivalente Vuex code illustreren een cruciaal verschil tussen de complexiteit van de bibliotheken. Laten we deze verschillen verder onderzoeken:

  • Directe versus indirecte statemutatie – Zoals de increment actie laat zien, muteren Pinia acties direct de state van de store. In Vuex kun je de state alleen veranderen met mutaties, die je moet vastleggen met acties. Deze processcheiding zorgt ervoor dat je state-veranderingen traceerbaar zijn, maar het is complexer en stijver dan vergelijkbare Pinia acties.
  • Asynchrone versus synchrone bewerkingen – Terwijl Vuex mutaties altijd synchroon zijn en geen asynchrone processen kunnen bevatten, kunnen Pinia acties zowel synchrone als asynchrone code bevatten. Als gevolg hiervan kun je API calls of andere asynchrone bewerkingen direct binnen acties uitvoeren, wat zorgt voor een slankere en beknoptere codebase.
  • Vereenvoudigde syntax – Vuex vereist vaak het definiëren van mutaties en het aanroepen van acties om ze te committen. Pinia maakt een einde aan deze noodzaak. De mogelijkheid om de staat te muteren binnen acties vermindert boilerplate code en houdt je bestaande code eenvoudiger. In Vuex vereisen basis state updates het definiëren van een actie en een mutatie, zelfs als de actie alleen de mutatie vastlegt.

De overgang van Vuex naar Pinia

Overstappen op Pinia kan veel voordelen bieden in eenvoud, flexibiliteit en onderhoudbaarheid, maar het vereist zorgvuldige planning en overweging om een succesvolle implementatie te garanderen.

Voordat je de overstap maakt, moet je voor het volgende zorgen:

  1. Raak vertrouwd met de verschillen tussen Pinia’s en Vuex’s architectuur, state management patterns en API’s. Inzicht in deze verschillen is cruciaal om je code effectief te refactoren en de functies van Pinia ten volle te benutten.
  2. Analyseer en refactoriseer je Vuex state, actions, mutations en getters zodat ze passen in Pinia’s structuur. Onthoud dat je in Pinia state definieert als een functie. Je kunt states direct muteren met acties en je kunt getters soepeler implementeren.
  3. Plan hoe je modules van je Vuex store overgaan. Pinia gebruikt modules niet op dezelfde manier als Vuex, maar je kunt nog steeds je stores structureren om vergelijkbare doelen te dienen.
  4. Maak gebruik van Pinia’s verbeterde TypeScript ondersteuning. Als je project TypeScript gebruikt, overweeg dan Pinia’s verbeterde type-inferentie en typemogelijkheden voor een betere typeveiligheid en ontwikkelaarservaring.
  5. Herzie je teststrategieën om veranderingen in state management aan te passen. Dit proces kan inhouden dat je moet aanpassen hoe je stores of acties in je unit- en integratietests mockt.
  6. Overweeg hoe de overgang de structuur en organisatie van je project beïnvloedt. Houd rekening met factoren zoals naamgevingsconventies en hoe je stores importeert en gebruikt in verschillende componenten.
  7. Zorg voor compatibiliteit met andere bibliotheken. Controleer of er updates of wijzigingen in dependencies nodig zijn die door de overgang beïnvloed kunnen worden.
  8. Evalueer eventuele prestatieveranderingen. Pinia is over het algemeen lichter dan Vuex, maar blijf de prestaties van je applicatie controleren tijdens en na de overgang om er zeker van te zijn dat er geen problemen zijn.

Het converteren van een store van Vuex naar Pinia bevat verschillende stappen om de verschillen in hun structuren en API’s op te vangen. Neem de Pinia store van eerder.

Dezelfde store in een Vuex store.js bestand ziet er als volgt uit.

import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);

export default new Vuex.Store({
    state: {
        count: 0,
    },
    mutations: {
        increment(state) {
            state.count++;
        },
    },
    actions: {
        increment(context) {
            context.commit('increment');
        },
    },
    getters: {
        doubleCount(state) {
            return state.count * 2;
        },
    },
});

Net als bij de vorige Pinia store bevat dit Vuex voorbeeld een state object met een enkele count property die is geïnitialiseerd op 0.

Het mutations object bevat methoden om de state direct te muteren, terwijl de methoden van het actions object de increment mutatie vastleggen.

Vervolgens bevat het getters object de doubleCount methode, die de count state vermenigvuldigt met 2 en het resultaat teruggeeft.

Zoals deze code laat zien, zijn er bij het implementeren van een store in Pinia een aantal opmerkelijke verschillen met Vuex:

  • Initialisatie – Pinia heeft Vue.use() niet nodig.
  • Structuur – In Pinia is de state een functie die een object retourneert, wat een betere TypeScript ondersteuning en reactiviteit mogelijk maakt.
  • Acties – Acties in Pinia zijn methoden die de state direct muteren zonder dat er mutaties nodig zijn, wat de code vereenvoudigt.
  • Getters – Hoewel vergelijkbaar met Vuex, worden Getters in Pinia gedefinieerd in de storedefinitie en hebben ze direct toegang tot de state.

Zo gebruik je de store in componenten

Met Vuex zou je de store als volgt kunnen gebruiken:

<template>
	<div>{{ doubleCount }}</div>
	<button @click="increment">Increment</button>
</template>

<script>
import { mapGetters, mapActions } from 'vuex';

export default {
	computed: {
	...mapGetters(['doubleCount']),
	},
	methods: {
	...mapActions(['increment']),
	},
};
</script>

Voor Pinia wordt het gebruik:

<template>
	<div>{{ store.doubleCount }}</div>
	<button> @click="store.increment">Increment</button>
</template>

<script>>
import { useStore } from '/src/store';

export default {
	setup() {
	const store = useStore();
	return {
		store,
	};
	},
};
</script>
Screenshot van de Pinia Store Demo landingspagina in verschillende stappen: 0, 2 en 4.
Pinia storeconversies.

Dit voorbeeld behandelt een eenvoudige conversie. Voor complexere Vuex stores, vooral die met modules, zou de conversie een meer gedetailleerde herstructurering inhouden om aan te sluiten bij de architectuur van Pinia.

Zo deploy je je Vue applicatie

Meld je voor het deployen aan voor een gratis trial van Kinsta’s Application Hosting dienst. Je zult de applicatie deployen met behulp van een Dockerfile.

Maak een Dockerfile aan in de root van je project en plak de volgende inhoud erin:

FROM node:latest
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY ./ .
CMD ["npm", "run", "start"]

Deze code instrueert Kinsta’s Docker engine om Node.js te installeren (FROM node:latest), de werkdirectory aan te maken (WORKDIR /app), de node modules uit het package.json bestand te installeren (RUN npm install) en het start (CMD ["npm", "run", "start"]) in die wordt aangeroepen wanneer de Vue app start. De commando’s COPY kopiëren de opgegeven bestanden of mappen naar de werkmap.

Daarna push je je code naar een Git provider van je voorkeur (Bitbucket, GitHub of GitLab). Als je repo klaar is, volg dan deze stappen om je app te deployen naar Kinsta:

  1. Log in of maak een account aan om je MyKinsta dashboard te bekijken.
  2. Autoriseer Kinsta met je Git provider.
  3. Selecteer Applicatie op de linker zijbalk en klik op de knop Applicatie toevoegen.
  4. Kies in het modal dat verschijnt de repository die je wilt deployen. Als je meerdere branches hebt, kun je de gewenste branch selecteren en een naam geven aan je applicatie.
  5. Selecteer een van de beschikbare datacenterlocaties.
  6. Kies je bouwomgeving en selecteer Dockerfile gebruiken om container image op te zetten.
  7. Als je Dockerfile niet in de root van je repo staat, gebruik dan Context om het pad aan te geven en klik op Doorgaan.
  8. Je kunt het Start commando leeg laten. Kinsta gebruikt npm start om je applicatie te starten.
  9. Selecteer de pod-grootte en het aantal instanties dat het meest geschikt is voor je app en klik op Doorgaan.
  10. Vul je creditcardgegevens in en klik op Applicatie maken.

Als alternatief voor applicatiehosting kun je ervoor kiezen om je Vue applicatie als een statische site te deployen met de gratis Statische Site Hosting van Kinsta.

Samenvatting

De overgang van Vuex naar Pinia is een belangrijke evolutie in state management binnen het Vue ecosysteem. Pinia’s eenvoud, verbeterde TypeScript ondersteuning en afstemming op Vue 3’s Composition API maken het een aantrekkelijke keuze voor moderne Vue applicaties.

Wanneer je zover bent om je Vue applicatie bij Kinsta te hosten, krijg je toegang tot een snelle, veilige en betrouwbare infrastructuur. Meld je aan bij Kinsta en maak gebruik van onze Applicatie Hosting dienst.

Jeremy Holcombe Kinsta

Content & Marketing Editor bij Kinsta, WordPress Web Developer en Content Writer. Buiten alles wat met WordPress te maken heeft, geniet ik van het strand, golf en films. En verder heb ik last van alle problemen waar andere lange mensen ook tegenaan lopen ;).