Pinia
#frontend
internal Slack channel for evaluation.Pinia is a tool for managing client-side state for Vue applications. Refer to the official documentation on how to use Pinia.
Best practices
Small stores
Prefer creating small stores that focus on a single task only. This is contrary to the Vuex approach which encourages you to create bigger stores.
Treat Pinia stores like cohesive components rather than giant state façades (Vuex modules).
Single file stores
Place state, actions, and getters in a single file.
Do not create ‘barrel’ store index files which import everything from actions.js
, state.js
and getters.js
.
If your store file gets too big it’s time to consider splitting that store into multiple stores.
Use Option Stores
Pinia offers two types of store definitions: option and setup. Prefer the option type when creating new stores. This promotes consistency and will simplify the migration path from Vuex.
Before Pinia
After Pinia
Migrating from Vuex
Decide what your primary state manager should be first. Proceed with this guide if Pinia was your choice.
Follow the official Vuex migration guide.
Try to split all your migrations into two steps:
- Refactor just the Vuex API: Don’t change the store structure, make sure it works in Pinia (example).
- Refactor the structure: Split your store into multiple smaller, single purpose stores.
Migration plan
If your store can’t be migrated in a single merge request then follow these steps for a smooth migration from Vuex to Pinia:
- Identify the stores you are going to migrate. Include all the stores that depend on your store and all the stores that you depend on.
- Create a migration issue, assign a migration DRI(s) and list all the stores you’re going to migrate. Track your migration progress in that issue. If necessary, split the migration into multiple issues.
-
Create a new CODEOWNERS (
.gitlab/CODEOWNERS
) rule for the store files you’re migrating, include all the Vuex module dependencies and store specs.If you are migrating only a single store then you would need to include only
state.js
(or yourindex.js
),actions.js
,mutations.js
andgetters.js
and their respective spec files.Assign at least two individuals responsible for reviewing changes made to the Vuex store. Always sync your changes from Vuex store to Pinia. This is very important so you don’t introduce regressions with the Pinia store.
- Copy existing store as-is to a new location (you can call it
stores/legacy_store
for example). Keep the file structure intact. - Create a store definition (
defineStore
) and only define your state in there. - Use code mods from the next section to migrate the store files. Import and use the migrated code in store’s definition.
- Migrate the store specs manually.
- Refactor components to use the new store.
- Remove the Vuex store.
- Remove CODEOWNERS rule.
- Close the migration issue.
Automated migration using codemods
You can use ast-grep codemods to simplify migration from Vuex to Pinia.
- Install ast-grep on your system before proceeding.
- Run
scripts/frontend/codemods/vuex-to-pinia/migrate.sh path/to/your/store
The codemods will migrate actions.js
, mutations.js
and getters.js
located in your store folder.
Manually scan these files after running the codemods to ensure they are properly migrated.
Vuex specs can not be automatically migrated, migrate them by hand.
Vuex module calls are replaced using Pinia conventions:
-
dispatch('anotherModule/action', ...args, { root: true })
→useAnotherModule().action(...args)
-
dispatch('action', ...args, { root: true })
→useRootStore().action(...args)
-
rootGetters['anotherModule/getter']
→useAnotherModule().getter
-
rootGetters.getter
→useRootStore().getter
-
rootState.anotherModule.state
→useAnotherModule().state
If you have not yet migrated a dependent module (useAnotherModule
and useRootStore
in the examples above) you can create a temporary dummy store.
Use the guidance below to migrate Vuex modules.
Migrating stores with nested modules
It is not trivial to iteratively migrate stores with nested modules that have dependencies between them. In such cases prefer migrating nested modules first:
- Create a Pinia store counterpart of the nested Vuex store module.
- Create a placeholder Pinia ‘root’ store for root module dependencies if applicable.
- Copy and adapt existing tests for the migrated module.
- Do not use migrated modules yet.
- Once all the nested modules are migrated you can migrate the root module and replace the placeholder store with the real one.
- Replace Vuex store with Pinia stores in components.