O framework Vue para JavaScript tornou-se popular para a criação de interfaces de usuário e aplicativos de página única (SPAs). Para garantir que seus aplicativos de grande porte funcionem de forma ideal, você precisa ter um bom domínio do gerenciamento de estado — o processo de gerenciar e centralizar os dados reativos de um aplicativo (estado) em vários componentes.

No Vue, o gerenciamento de estado há muito tempo depende do Vuex, uma biblioteca com armazenamento centralizado para todos os componentes de um aplicativo. No entanto, avanços recentes no ecossistema Vue deram origem ao sucessor do Vuex, o Pinia.

O Pinia oferece uma abordagem de gerenciamento mais leve, modular e intuitiva. Ele se integra perfeitamente ao sistema de reatividade e à API de Composição do Vue, tornando fácil para os desenvolvedores gerenciar e acessar o estado compartilhado de forma escalonável e sustentável.

Definindo o cenário: Pinia vs Vuex

Como biblioteca de referência para gerenciamento de estado em aplicativos Vue, o Vuex fornecia uma store centralizada para todos os componentes de um aplicativo. No entanto, com o avanço do Vue, o Pinia representa uma solução mais moderna. Vamos explorar como ele se diferencia do Vuex.

  • Diferenças de API — A API de Composição do Pinia oferece uma API mais fundamental e intuitiva que o Vuex, tornando mais simples gerenciar o estado do aplicativo. Além disso, sua estrutura se assemelha bastante à API de Opções do Vue, familiar para a maioria dos desenvolvedores de Vue.
  • Suporte a tipos — Historicamente, muitos desenvolvedores de Vue têm tido dificuldades com o suporte limitado a tipos do Vuex. Em contrapartida, o Pinia é uma biblioteca de gerenciamento de estado totalmente tipada que elimina essas preocupações. Sua segurança de tipos ajuda a evitar possíveis erros de runtime, contribui para a legibilidade do código e possibilita um escalonamento mais suave.
  • Sistema de reatividade — Ambas as bibliotecas aproveitam o sistema de reatividade do Vue, mas a abordagem do Pinia se alinha melhor com a API de Composição do Vue 3. Embora a API de reatividade seja poderosa, o gerenciamento de estados complexos em grandes aplicativos pode ser um desafio. Felizmente, a arquitetura simples e flexível do Pinia diminui a complexidade de gerenciamento de estado em seus aplicativos Vue 3. O padrão de store do Pinia permite que você defina uma store para gerenciar uma parte específica do estado do aplicativo, simplificando sua organização e compartilhando-a entre componentes.
  • Natureza leve — Com apenas 1 KB, o Pinia se integra perfeitamente ao seu ambiente de desenvolvimento, e sua natureza leve pode melhorar o desempenho e os tempos de carregamento do aplicativo.

Como configurar um projeto Vue com o Pinia

Para integrar o Pinia em um projeto Vue, inicialize seu projeto com o Vue CLI ou o Vite. Após a inicialização do projeto, você pode instalar o Pinia via npm ou yarn como uma dependência.

  1. Crie um novo projeto Vue usando o Vue CLI ou o Vite. Então siga as instruções para configurar seu projeto.
    // Using Vue CLI
    vue create my-vue-ap
    // Using Vite
    npm create vite@latest my-vue-app -- --template vue
  2. Altere seu diretório para a pasta do projeto recém-criado:
    cd my-vue-app
  3. Instale o Pinia como uma dependência em seu projeto.
    // Using npm
    npm install pinia
    // Using yarn
    yarn add pinia
  4. Em seu arquivo de entrada principal (geralmente main.js ou main.ts), importe o Pinia e diga ao Vue para usá-lo:
    import { createApp } from 'vue';
    import { createPinia } from 'pinia';
    import App from './App.vue';
    
    const app = createApp(App);
    
    app.use(createPinia());
    app.mount('#app');

    Com o Pinia instalado e configurado em seu projeto Vue, você está pronto para definir e usar stores para gerenciamento de estado.

Como criar uma store no Pinia

A store é a espinha dorsal do gerenciamento de estado em seu aplicativo Vue com Pinia. Ela o ajuda a gerenciar os dados de todo o aplicativo de forma coesa e coordenada. É na store que você define, armazena e gerencia os dados a serem compartilhados entre os vários componentes do seu aplicativo.

Essa centralização é fundamental, pois define a estrutura e organiza as alterações de estado do seu aplicativo, tornando o fluxo de dados mais previsível e fácil de depurar.

Além disso, uma store no Pinia faz mais do que manter o estado. As funcionalidades incluídas no Pinia permitem atualizar o estado por meio de ações e calcular estados derivados usando getters. Esses recursos incorporados contribuem para uma base de código mais eficiente e de fácil manutenção.

O exemplo a seguir ilustra a criação de uma store básica do Pinia em um arquivo src/store.js do projeto.

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

Como acessar o estado da store nos componentes

Em comparação com o Vuex, a abordagem do Pinia para acesso e gerenciamento de estado é mais intuitiva, especialmente se você estiver familiarizado com a API de Composição do Vue 3. Essa API é um conjunto de vários elementos que permitem a inclusão de lógica reativa e componível em seus componentes.

Considere o código a seguir.

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

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

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

No snippet acima, a tag <template> contém a marcação HTML definida de seu componente. Para exibir o valor da propriedade count da store do Pinia, você usa a sintaxe de vinculação de dados do Vue, expressa como {{ count }}.

A função useStore fornece acesso à store do Pinia, portanto você a importa de store.js usando import { useStore } from './store';.

Um recurso da API de Composição do Vue 3, a função setup define o estado reativo e a lógica do seu componente. Dentro da função, você chama useStore() para acessar a store do Pinia.

Em seguida, const count = store.count acessa a propriedade count da store, tornando-a disponível no componente.

Por fim, setup retorna count, permitindo que o template a renderize. O sistema de reatividade do Vue significa que o template do seu componente atualizará o valor de count sempre que ele for alterado na store.

Abaixo está uma captura de tela do resultado.

Captura de tela do template Pinia Store Demo carregado em um navegador.
Captura de tela do template Pinia Store Demo carregado em um navegador.

Esse exemplo ilustra as vantagens do Pinia:

  • Simplicidade — O Pinia permite acesso direto ao estado da store sem funções de mapeamento. Em contraste, o Vuex precisa de mapState (ou helpers similares) para obter o mesmo acesso.
  • Acesso direto à store — O Pinia permite que você acesse diretamente propriedades de estado (como store.count), tornando seu código mais legível e compreensível. Enquanto isso, o Vuex geralmente requer getters para acessar até mesmo propriedades fundamentais, adicionando complexidade que diminui a legibilidade.
  • Compatibilidade com a API de Composição — Como o método de configuração demonstra, a integração do Pinia com a API de Composição se alinha especialmente bem com o desenvolvimento moderno do Vue, proporcionando uma experiência de codificação mais uniforme.

Como modificar o estado com o Pinia

No Pinia, você modifica o estado de uma store usando ações, que são mais flexíveis do que as mutações do Vuex. Considere a seguinte chamada de função, que incrementa a propriedade count do estado:

store.increment(); // Increments the count

Por outro lado, um equivalente em Vuex envolve a definição de uma mutação, além de pelo menos uma ação:

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

A ação no Pinia e o código equivalente em Vuex exemplificam uma diferença crucial na complexidade de código das bibliotecas. Vamos explorar melhor essas diferenças:

  • Mutação de estado direta vs indireta — Como demonstra a ação increment, as ações no Pinia alteram diretamente o estado da store. No Vuex, você só pode alterar o estado usando mutações, que devem ser confirmadas com o commit de ações. Essa separação de processos garante que suas alterações de estado sejam rastreáveis, mas é mais complexa e rígida do que ações equivalentes no Pinia.
  • Operações assíncronas vs síncronas — Enquanto as mutações do Vuex são sempre síncronas e não podem conter processos assíncronos, as ações do Pinia podem conter código síncrono e assíncrono. Como resultado, você pode realizar chamadas de API ou outras operações assíncronas diretamente nas ações, o que torna a base de código mais enxuta e concisa.
  • Sintaxe simplificada — O Vuex geralmente requer a definição de mutações e a chamada de ações para confirmá-las mediante o commit. O Pinia elimina essa necessidade. A capacidade de alterar o estado dentro das ações reduz código boilerplate e mantém seu código existente mais simples. No Vuex, atualizações básicas de estado exigem a definição de uma ação e de uma mutação, mesmo que a ação esteja apenas fazendo o commit da mutação.

A transição do Vuex para o Pinia

A transição para o Pinia pode proporcionar inúmeros benefícios em termos de simplicidade, flexibilidade e facilidade de manutenção, mas requer planejamento e consideração cuidadosos para garantir uma implementação bem-sucedida.

Antes de fazer a mudança, certifique-se de:

  1. Estar familiarizado com as diferenças entre a arquitetura, os padrões de gerenciamento de estado e as APIs do Pinia e do Vuex. Compreender essas diferenças é fundamental para refatorar seu código com eficácia e aproveitar ao máximo os recursos do Pinia.
  2. Analisar e refatorar o estado, as ações, as mutações e os getters do Vuex para ajustá-los à estrutura do Pinia. Lembre-se: no Pinia, você define o estado como uma função. Você pode alterar diretamente os estados com ações e implementar getters com mais facilidade.
  3. Planejar como fazer a transição dos seus módulos de store Vuex. O Pinia não usa módulos da mesma forma que o Vuex, mas você ainda pode estruturar suas stores para servirem a propósitos similares.
  4. Aproveitar o suporte aprimorado do Pinia para TypeScript. Se o seu projeto usa TypeScript, considere os recursos aprimorados de inferência de tipo e tipagem do Pinia para melhorar a segurança de tipos e a experiência do desenvolvedor.
  5. Revisar suas estratégias de teste para acomodar alterações no gerenciamento de estado. Esse processo pode envolver atualizar a forma como você simula stores ou ações em seus testes unitários e de integração.
  6. Considerar como a transição afeta a estrutura e a organização do seu projeto. Leve em conta fatores como convenções de nomenclatura e como você importa e usa stores entre componentes.
  7. Garantir a compatibilidade com outras bibliotecas. Verifique se há atualizações necessárias ou alterações de dependência que a transição possa afetar.
  8. Avaliar todas as alterações de desempenho. O Pinia geralmente é mais leve que o Vuex, mas continue monitorando o desempenho do seu aplicativo durante e após a transição para garantir que não haja problemas.

A conversão de uma store de Vuex para Pinia envolve várias etapas para acomodar as diferenças em suas estruturas e APIs. Considere a store Pinia do exemplo anterior.

A mesma store em um arquivo store.js do Vuex aparece da seguinte forma.

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;
        },
    },
});

Assim como a store anterior no Pinia, esse exemplo do Vuex contém um objeto state com uma única propriedade count inicializada como 0.

O objeto mutations contém métodos para alterar diretamente o estado, enquanto os métodos do objeto actions fazem o commit da mutação increment.

Em seguida, o objeto getters contém o método doubleCount, que multiplica o estado count por 2 e retorna o resultado.

Como esse código demonstra, implementar uma store no Pinia envolve várias diferenças perceptíveis em relação ao Vuex:

  • Inicialização — O Pinia não requer Vue.use().
  • Estrutura — No Pinia, o estado é uma função que retorna um objeto, permitindo melhor suporte a TypeScript e reatividade.
  • Ações — Ações no Pinia são métodos que alteram diretamente o estado sem necessidade de mutações, simplificando o código.
  • Getters — Embora semelhantes aos do Vuex, os Getters do Pinia são definidos na definição da store e podem acessar diretamente o estado.

Como usar a store em componentes

Com Vuex, você poderia usar a store da seguinte forma:

<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>

Para o Pinia, essa utilização se torna:

<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>
Conversões de store do Pinia.
Conversões de store do Pinia.

Este exemplo aborda uma conversão básica. Para stores Vuex mais complexas, especialmente as que usam módulos, a conversão envolveria uma reestruturação mais detalhada para alinhar com a arquitetura do Pinia.

Como implantar seu aplicativo Vue

Antes da implantação, inscreva-se para uma avaliação gratuita do serviço de Hospedagem de Aplicativos da Kinsta. Você implantará o aplicativo com a ajuda de um Dockerfile.

Crie um Dockerfile na raiz do seu projeto e cole o seguinte conteúdo:

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

Esse código instrui o mecanismo Docker da Kinsta a instalar o Node.js (FROM node:latest), criar o diretório de trabalho (WORKDIR /app), instalar os módulos do node a partir do arquivo package.json (RUN npm install) e definir o comando start (CMD ["npm", "run", "start"]) que será chamado quando o aplicativo Vue for iniciado. Os comandos COPY copiam os arquivos ou diretórios especificados para o diretório de trabalho.

Depois disso, envie seu código para um provedor Git de preferência (Bitbucket, GitHub ou GitLab). Quando seu repositório estiver pronto, siga estas etapas para implantar seu aplicativo na Kinsta:

  1. Faça login ou crie uma conta para visualizar seu painel MyKinsta.
  2. Autorize a Kinsta com seu provedor Git.
  3. Selecione Aplicativo na barra lateral esquerda e clique no botão Adicionar aplicativo.
  4. No modal que aparece, escolha o repositório que você deseja implantar. Se você tiver vários branches, pode selecionar o branch desejado e dar um nome ao seu aplicativo.
  5. Selecione um dos locais de centros de dados disponíveis.
  6. Escolha seu ambiente de build e selecione Utilize o Dockerfile para configurar a imagem do contêiner.
  7. Se o seu Dockerfile não estiver na raiz do seu repositório, use Contexto para indicar o caminho e clique em Continuar.
  8. Você pode deixar a entrada Comando start vazia. A Kinsta usa npm start para iniciar seu aplicativo.
  9. Selecione o tamanho do pod e o número de instâncias mais adequado para o seu aplicativo e clique em Continuar.
  10. Preencha as informações do seu cartão de crédito e clique em Criar aplicativo.

Como alternativa à hospedagem de aplicativos, você pode optar por implantar gratuitamente seu aplicativo Vue como um site estático na Kinsta com a Hospedagem de site estático.

Resumo

A transição do Vuex para o Pinia marca uma evolução significativa no gerenciamento de estado dentro do ecossistema Vue. A simplicidade, o suporte aprimorado ao TypeScript e o alinhamento com a API de Composição do Vue 3 favorecem a escolha do Pinia para aplicativos Vue modernos.

Quando estiver pronto para hospedar seu aplicativo Vue com a Kinsta, você terá acesso a uma infraestrutura rápida, segura e confiável. Inscreva-se na Kinsta e use nosso serviço de hospedagem de aplicativos.

Jeremy Holcombe Kinsta

Editor de Conteúdo & Marketing na Kinsta, Desenvolvedor Web WordPress e Escritor de Conteúdo. Fora do universo WordPress, eu curto praia, golfe e filmes. Também enfrento problemas de gente alta ;).