Architetural Considerations for VueJS project: Implementing Vuex - vue.js

Our front-end team is presently working on a Reporting application with the following features:
Dashboards
Portfolio Analysis Tool (search form that returns grid-based results)
Automated Reports page
We've decided to architect the above using VueJS with the Webpack boilerplate (via Vue-Cli) and are trying to design to have common components:
A report component
Has title, description, type (grid, visualization, etc.) and some setting parameters
A report list component
Has a title and an array of report components as its properties
A dashboard that has an array of report list components arranged in a grid
Some requirements
A dashboard component can have 4 or more report list components, each with multiple reports that can be selected for view by the user from a report list select menu. Each report component can have one or more setting parameters that the user can manipulate and submit to re-render the report. A report can be a grid (ag-grid in our case) or a visualization-based report. Lastly, there is also authentication via Auth0.
Questions
Does it make sense to use Vuex to manage state for all our components and related interactions?
Does it sound like the application is a good use-case for Vuex?
If so, why? Is it better than using component to component communication via the built in Vue mechanisms (for parent-child, sibling-sibling components)?
Thank you in advance for helping us make a decision.

Vuex is useful when you have multiple components that need the same state. In your case, you're displaying reports in lots of different places and formats. This is a great use case for Vuex in my opinion.
Now, i don't know if your team is familiar with Vue, but passing data via props is a PITA. Especially if the components that need the data are spread far away in the component hierarchy, and deeply nested, which they usually are. Anyone who's been thru the gauntlet of passing props and emitting events up multiple levels will tell you that.
With Vuex, it's a single function call to get your data, from ANYWHERE in the component hierachy. It's a breath of fresh air.

I voted to close this question, because the answer is highly opinionated.
I've built multiple projects with Vue, some with dozens of components and many multiple thousands of lines of code. I've never once felt the level of complexity rose to the level that I needed Vuex.
You've described an application with half a dozen components.
I've definitely abstracted my logic out into custom objects, but that's just javascript.
YMMV.

Related

Why Pinia vs Vuex for Vue 3? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 months ago.
This post was edited and submitted for review 7 months ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
I am a Vue.js developer who is coming up to speed with the the new features added to Vue 3, from Vue 2, namely the Composition API (added in Vue 3).
For State Management, it appears that along with the release of Vue 3, the community is shifting from using Vuex to Pinia.
What is the difference between Pinia vs Vuex? Conceptually, what has changed from Vue 2 to Vue 3, that makes Pinia a better fit for Vue 3?
Thank you.
In short, Pinia's API is much simpler and intuitive. It makes using stores a breeze, even for junior devs.
It brings the benefits of Composition API, but has a structure which greatly resembles the Options API, which you're probably familiar with:
has a reactive state, equivalent of data function in Options API
has getters, equivalent of computed in Options API
has actions, equivalent of methods in Options API
does not have mutations, as any change to state now registers an implicit mutation, regardless of where it's performed
Additionally, in Pinia:
actions are no longer necessarily async, they can be either
actions don't need (and don't have) the first param (action context) as you no longer need commit, dispatch, rootGetters, rootState
other stores can now be invoked directly in any actions/getters, even allowing cyclic dependencies; this reduces the need to nest stores, although still possible
all stores are now dynamically registered at runtime (when they are invoked for the first time; the store starts empty)
inside actions and getters functions, this is the current store and provides direct access to all state props, actions and getters
you also have typed direct access to all actions, getters and state props on the object returned by the function (e.g: useSomeStore) returned by defineStore(); it's all TypeScript friendly, no workarounds or type casting required.
More in-depth explanations and reasoning on the dedicated page to differences between the two plugins.
According to declarations by plugin authors, Vuex 5 will have a similar API to Pinia's and they are likely to merge at some point.
As outlined in comments by Tony, Pinia is now the officially recommended state management solution by Vue team.
Vuex is now in maintenance mode. It still works, but will no longer receive new features. It is recommended to use Pinia for new applications. -- [added by Evan You in dec 2021].
Ref:
"what has changed from Vue 2 to Vue 3, that makes Pinia a better fit for Vue 3?"
Pinia was designed for usage in setup(). So much so, that it has a dedicated page on how to use it outside of setup().
More importantly, you are implying Vuex is a better fit for Vue2 projects.
Technically, that is false.
Both plugins offer the same functionality but Vuex has more boilerplate and, overall, a less intuitive syntax. Therefore it requires better trained engineers, for longer periods of time.
If you choose Vuex, your project costs will grow proportionally with your project's complexity, without any benefits.
I want to take a moment to answer my own question, after doing some research and giving a talk on this at the Vuejs LA Meetup (Los Angeles). Thanks also to the others who already answered to help with this response.
TLDR: In Vue 2 you -could not- easily control the shared Global State using "just Vue," so you needed Vuex to manage Global State shared throughout your app. (You can manage a component's local state, but not "Global State" that is the shared state across your app, without using something like Vuex.) In Vue 3, using the Composition API, you -can- create a place to manage Global State, so you can very easily just "roll your own" State Management system. So now, in Vue 3, yes, you basically can do this on your own, but you might as well use a standard one everyone is using, Pinia.
Full Explanation: For those who are coming up to speed with Vue 3, the big addition is the Composition API. For Vue 3, Vue 2 basically got re-branded the "Options API" and now there is an additional "Composition API." Please don't confuse "new" with "better." The Composition API is not better. It's just different. The Options API (aka, the Vue2 way of doing things is still fantastic -- and you should continue to use it).
The main difference between with Options API and the Composition API is organizational. The Options API (again, aka The Vue 2 Way) helps you organize your code a certain standard way -- basically one of the best features of Vue is the clean organization of each component. Those 3 <template>/<script>/<styles> blocks in each .vue component make it a pleasure to use Vue.
The Composition API was basically created for the occasion that you need to break out of that paradigm. Imagine you need to have the same logic, like Search, in the <script> section of your code. But you need the Search ability in 3 places. Instead of having the same redundant code three times, you can now extract that Search code to a new file, call it something like my-search.js, and access that search code from one place by importing its functionality into each of your components, staying DRY. Moreso, using the Composition API you can do this while maintaining reactivity (in Vue 2, you could have an external file, but you were basically "leaving Vue" and that was a problem). Now, using the Composition API in Vue 3, you can create a separate area to focus on shared logic, like my-search.js, and Vue continues to be aware of it, so you don't break reactivity.
In Vue 2, the community solved this Global State Management issue by creating Vuex. It was a plugin that allowed you to control state outside of the components, i.e., control Global State while remaining reactive (i.e., it did not break state).
Let's apply this new ability given to us by the Composition API to Managing Global State. If you can create a new external.js file that remains functional within your Vue app, that retains state, you can easily write your own Global State Manager (replicating what Vuex does). Imagine creating a file called global-state.js and making all of your Global State updates there. The Composition API makes this super easy to do.
So now, because of the Composition API in Vue 3, we basically do not need any external state management tool. That is why, when Vue 3 launched, every forum post was asking questions like, "Why do we even need Vuex anymore?" In Vue 3, we don't need Vuex anymore because we can Manage Global State on our own using the Composition API.
So last, why Pinia? Well, basically, standards. We could all roll our own, but we might as well use a light-weight plugin that is standardized (I would bet that Pinia is written using the Composition API — please correct me if I'm wrong here). Moreso, because it's a standardized process, and the new community-backed way of handling Global State Management, it comes with the bonus of integrating well into the rest of the Vue ecosystem of tools, like Vue DevTools, and has its own plugin system.
Hope that helps answer the original questions I was asking, focused on the concept: "Conceptually, what has changed from Vue 2 to Vue 3, that makes Pinia a better fit for Vue 3."

Vue: wait to render until all components are mounted

I have a Vue/Nuxt web app where pages are dynamically generated from lots of components that have child components.
The trouble is the header and footer are rendered first, then the child components that have the actual content. This looks terrible on first load and Lighthouse doesn't like it. It's an Avoid large layout shifts failure. For context it's only an issue when client side rendering, SSR would eliminate this issue while intoducing others.
What I could do is edit every single component in my project and add an event on mounted. That could then be used to decide when to show the layout. The problem is it would be a major hassle and would cause bugs when new components are added and this bit is forgotten.
I'm not able to find any general solution to this in Vue and/or Nuxt. I'd love to have a new lifetime hook of allMounted which would only fire when child components are also mounted but it doesn't exist. Even that would be a bit hacky. An even more general render when all components are mounted option would be awesome.
I'm not sure that a dynamic component can help in your case, but I guess that your company's website will not really benefit from this. Indeed, the problem of the content jumping will still be present IMO.
<component :is="currentTabComponent"></component>
I still think that you content is highly static IMO and that you could even switch to full static to have the best performance benefits rather than having to wait for a long time (TTFB) while SPA is loading all the content. It may be a bit more challenging to have everything look nice of course (before/after the hydration).
Also, you should have an idea of the approximate size of your containers. In that case, you could use some skeletons and a maybe even a prototyping font to visually populate the blocks.
In case you do not agree or think that this is not doable, you still have this solution to your disposal
<child-component #hook:mounted="makeSomeStuff"></child-component>
With this you may be able to display a full-sized loader until your content is done loading. You could add a mixin with the longer mounted syntax in each component to avoid too much boilerplate but this one is deprecated and do have various issues.
But IMO, the issue is more in your way of fetching the data (asyncData and fetch hooks are nice) and the way that everything is full dynamic when there is no specific need. If it's more important to keep the dynamic part, I guess that you can be serious on code reviews or plug some git hooks or alike to kinda scan the code and see if the required mounted emits are in place.
There is no ideal solution in your case but keep in mind that Lighthouse will always prefer some SSR content with the less amount of JS. Here is my personal bible to anything performance related, you could probably grasp some nice tips in this really in-depth article.
Update for Vue3
The syntax has changed for Vue3: https://v3-migration.vuejs.org/breaking-changes/vnode-lifecycle-events.html#_2-x-syntax

Using Vuex in Vuejs application

I am new to Vue.js. I learned about a concept known as vuex. Please could anyone provide me explanation as to when should I use vuex.
If you’re working on a rather simple application or if all you do is to replace some parts of your (server rendered) application with some Vue.js magic, you might actually be fine not using Vuex at all.
On the other hand, if you’re working on a large scale single page app, you may encounter situations where you need the same data at two completely different places in your application. This is the point at which a centralized state management tool like Vuex oftentimes makes a lot of sense.
You can find more on : https://markus.oberlehner.net/blog/should-i-store-this-data-in-vuex/
If you have been through the documentation of Vuex on the first page you would have seen a headline When Should I Use It?. That gives a perfect view of when to use Vue.
You can use Vuex in any type of applications, small, medium or large scale. That's totally up to you. But it too overwhelming to use it in a small project because you have to write down a lot of code to get started with. Which can be easily maintained by the component state.
But it comes handy when the application is large. Managing state outside the Vue component will be a necessity and Vuex will be the natural next step for you.
Vuex is a flux implementation specifically for vue, and is officially supported by vue.js.
Well let's talk some plain English. In general, while developing a front end application using component driven frameworks like angular, react, vue, etc,. we need to start with developing components as they are basic as well as complex building block of the application. Usually a small/mid size project will have 5-10 components. And could go to any number in larger applications . These components would at many places need to communicate with each other so as to pass data.
The flow of data can go in one of the three directions:
Parent Component to Child component
Child Component to Parent component
Sibling Components
In order to achieve one, two or all the three of the above, there are ways to let the data flow. Some of the ways in vue.js are props(parent to child), events($emit, $on - child to parent), services(event driven) and vuex.
So let's just talk about vuex for now, i.e., when should you go for vuex and not other above mentioned methods.
When number of components are high. It would be a big pain if each component will have to maintain their own data in application level. Vuex solves it with state(storing state) and getters(getting state).
When you want to share data between siblings components. Props and Events would be the last thing you would want to do. Vuex just makes it easy. One of the sibling component will mutate the global state and other can just get it using getters (try mapGetters in computed properties of the component)
When too many components are updating the data. That's where vuex's mutations comes handly. Mutations are always synchronous. In case you want to work with async tasks then use actions.
Well this list can on and on...
Personally I like to follow this:
When the number of components and communication between them is high. Use vuex to manage state more conveniently and to make life easier.
I hope it helps.
Vuex is used to pass/store data between components so that it can be used or edited anywhere within your application.
You need to weigh up the benefits of using Vuex over the extra work that is required to set it up. It can be a very valuable tool when your application gets quite large but on the other hand when working with a small application the amount of time/effort/code to get it set up might out weigh the benefits of actually using it.
Using a centralised data store such as vuex is only really needed in a large scale app where you need to access data at different stages throughout the app.
Here is a quick link that further explains:
https://vuex.vuejs.org/
There is also centralised state management that is not vuex that can be useful when working with smaller scale apps which is detailed in this link
https://v2.vuejs.org/v2/guide/state-management.html

Angular 6 - Why use #ngrx/store rather than service injection

I am recently learning Angular 6 with #ngrx/store while one of the tutorial is to use #ngrx/store for state management, however I don't understand the benefit of using #ngrx/store behind the scene.
For example, for a simple login and signup action, previously by using the service(Let's call it AuthService) we might use it to call the backend api, store "userInfo" or "token" in the AuthService, redirect user to "HOME" page and we can inject AuthService in any component where we need to get the userInfo by using DI, which simply that one file AuthService handles everything.
Now if we are using #ngrx/store, we need to define the Action/State/Reducer/Effects/Selector which probably need to write in 4 or 5 files to handle above action or event, then sometimes still we need to call backend api using service, which seems much much more complicated and redundant...
In some other scenario, I even see some page uses #ngrx/store to store the object or list of object like grid data., is that for some kind of in-memory store usage?
So back to the question, why are we using #ngrx/store over service registration store here in Angular project? I know it's for "STATE MANAGEMENT" usage, but what exactly is the "STATE MANAGEMENT"? Is that something like transaction log and When do we need it? Why would we manage it on the front end? Please feel free to share your suggestion or experience in the #ngrx/store area!
I think you should read those two posts about Ngrx store:
Angular Service Layers: Redux, RxJs and Ngrx Store - When to Use a Store And Why?
Ngrx Store - An Architecture Guide
If the first one explains the main issues solved by Ngrx Store, it also quote this statement from the React How-To "that seems to apply equally to original Flux, Redux, Ngrx Store or any store solution in general":
You’ll know when you need Flux. If you aren’t sure if you need it, you don’t need it.
To me Ngrx store solves multiple issues. For example when you have to deal with observables and when responsability for some observable data is shared between different components. In this case store actions and reducer ensure that data modifications will always be performed "the right way".
It also provides a reliable solution for http requests caching. You will be able to store the requests and their responses, so that you could verify that the request you're making has not a stored response yet.
The second post is about what made such solutions appear in the React world with Facebook's unread message counter issue.
Concerning your solution of storing non-obvervable data in services. It works fine when you're dealing with constant data. But when several components will have to update this data you will probably encounter change detection issues and improper update issues, that you could solve with:
observer pattern with private Subject public Observable and next function
Ngrx Store
I'm almost only reading about the benefits of Ngrx and other Redux like store libraries, while the (in my opinion) costly tradeoffs seem to be brushed off with far too much ease. This is often the only reason that I see given: "The only reason not to use Ngrx is if your app is small and simple". This (I would say) is simply incomplete reasoning and not good enough.
Here are my complaints about Ngrx:
You have logic split out into several different files, which makes the code hard to read and understand. This goes against basic code cohesion and locality principles. Having to jump around to different places to read how an operation is performed is mentally taxing and can lead to cognitive overload and exhaustion.
With Ngrx you have to write a lot more code, which increases the chances of bugs. More code -> more places for bugs to appear.
An Ngrx store can become a dumping ground for all things, with no rhyme or reason. It can become a global hodge podge of stuff that no one can get a coherent overview of. It can grow and grow until no one understands it any more.
I've seen a lot of unnecessary deep object cloning in Ngrx apps, which has caused real performance issues. A particular app I was assigned to work on was taking 40 ms to persist data in the store because of deep cloning of a huge store object. This is over two lost render frames if you are trying to hit a smooth 60 fps. Every interaction felt janky because of it.
Most things that Ngrx does can be done much simpler using a basic service/facade pattern that expose observables from rxjs subjects.
Just put methods on services/facades that return observables - such a method replaces the reducer, store, and selector from Ngrx. And then put other methods on the service/facade to trigger data to be pushed on these observables - these methods replace your actions and effects from Ngrx. So instead of reducers+stores+selectors you have methods that return observables. Instead of actions+effects you have methods that produce data the the observables. Where the data comes from is up to you, you can fetch something or compute something, and then just call subject.next() with the data you want to push.
The rxjs knowledge you need in order to use ngrx will already cause you to be competent in using bare rxjs yourself anyways.
If you have several components that depend on some common data, then you still don't need ngrx, as the basic service/facade pattern explicitly handles this already.
If several services depend on common data between them, then you just make a common service between these services. You still don't need ngrx. It's services all the way down, just like it is components all the way down.
For me Ngrx doesn't look so good on the bottom line.
It is essentially a bloated and over engineered Enterprise™🏢👨‍💼🤮 grade Rxjs Subject, when you could have just used the good old and trusty Rxjs Subject. Listen to me kids, life is too short for unnecessary complexity. Stick to the bare necessities. The simple bare necessities. Forget about your worries and your strife.
I've been working with NgRx for over three years now. I used it on small projects, where it was handy but unnecessary and I used it in applications where it was perfect fit. And meanwhile I had a chance to work on the project which did not use it and I must say it would profit from it.
On the current project I was responsible for designing the architecture of new FE app. I was tasked to completely refactor the existing application which for the same requirements used non NgRx way and it was buggy, difficult to understand and maintain and there was no documentation. I decided to use NgRx there and I did it because of following reasons:
The application has more than one actor over the data. Server uses
the SSE to push state updates which are independent from user
actions.
At the application start we load most of available data which are
then partially updated with SSE.
Various UI elements are enabled/disabled depending on multiple
conditions which come from BE and from user decisions.
UI has multiple variations. Events from BE can change currently
visible UI elements (texts in dialogs) and even user actions might
change how UI looks and works (recurring dialog can be replaced by
snack if user clicked some button).
State of multiple UI elements must be preserved so when user leaves
the page and goes back the same content (or updated via SSE) is
visible.
As you can see the requirements does not meet the standard CRUD operations web page. Doing it the "Angular" way brought such complexity to the code that it became super hard to maintain and what's worst by the time I joined the team the last two original members were leaving without any documentation of that custom made, non NgRx solution.
Now after the year since refactoring the app to use NgRx I think I can sum up the pros and cons.
Pros:
The app is more organized. State representation is easy to read,
grouped by purpose or data origin and is simple to extend.
We got rid of many factories, facades and abstract classes which lost
their purpose. The code is lighter, and components are 'dumber', with
less hidden tricks coming from somewhere else.
Complicated state calculations are made simple using effects and
selectors and most components can be now fully functional just by
injecting the store and dispatching the actions or selecting the
needed slice of the state while handling multiple actions at once.
Because of updated app requirements we were forced to refactor the
store already and it was mostly Ctrl + C, Ctrl + V and some renaming.
Thanks to Redux Dev Tools it is easier to debug and optimize (yep
really)
This is most important - even thought our state itself is unique the
store management we are using is not. It has support, it has
documentation and it's not impossible to find solutions to some
difficult problems on the internet.
Small perk, NgRx is another technology you can put to your CV :)
Cons:
My colleagues were new to the NgRx and it took some time for them to
adapt and fully understand it.
On some occasions we introduced the issue where some actions were
dispatched multiple times and it was difficult to find the cause of
it and fix it
Our Effects are huge, that's true. They can get messy but that's what
we have pull requests for. And if this code wasn't there it would
still end up somewhere else :)
Biggest issue? Actions are differentiated by their string type. Copy
an action, forget to rename it and boom, something different is
happening than you expect, and you have no clue why.
As a conclusion I would say that in our case the NgRx was a great choice. It is demanding at first but later everything feels natural and logical. Also, when you check the requirements, you'll notice that this is a special case. I understand the voices against NgRx and in some cases I would support them but not on this project. Could we have done it using 'Angular' way? Of course, it was done this way before, but it was a mess. It was still full of boiler plate code, things happening in different places without obvious reasons and more.
Anyone who would have the chance to compare those two versions would say the NgRx version is better.
There is also a 3rd option, having data in service and using service directly in html, for instance *ngFor="let item of userService.users". So when you update userService.users in service after add or update action is automatically rendered in html, no need for any observables or events or store.
If the data in your app is used in multiple components, then some kind of service to share the data is required. There are many ways to do this.
A moderately complex app will eventually look like a front end back end structure, with the data handling done in services, exposing the data via observables to the components.
At one point you will need to write some kind of api to your data services, how to get data in and out, queries, etc. Lots of rules like immutability of the data, and well defined single paths to modify the data. Not unlike the server backend, but much quicker and responsive than the api calls.
Your api will end up looking like one of the many state management libraries that already exist. They exist to solve difficult problems. You may not need them if your app is simple.
NGRX sometimes has a lot of files and a lot of duplicate code. Currently working on a fix for this. To make generic type classes for certain NGRX state management situations that are very common inside an Angular project like pagers and object loading from back-ends

How to select a Mapbox Vuejs component package

I'm currently building a VueJS app the will have map components in different formats on multiple pages. I'm therefore evaluating some existing components: vue-mapbox and vue-mapbox-gl (listed as mapbox-gl-vue on npmjs.com) and would like input on a choice criteria.
vue-mapbox has 37 stars on github and has peaked at about 86 downloads a week on npm.
vue-mapbox-gl has 87 stars on github and has seen a much more popular download history at around 1000 per week on npm.
Both projects seem to be under active development.
Apart from this difference in popularity, the main difference I see between the packages is vue-mapbox has adopted a more granular approach to creating sub-components (like markers and controls), whereas vue-mapbox-gl gives you a single map component and then you implement markers, clusters, controls, etc., withing the script tags of your base component. To my way of thinking, this is not really the 'vuejs way' where you create reusable components. However, vue-mapbox-gl is significantly more popular.
How would you choose? Or, would you skip component packages completely and write your own?
EDIT
Based on comments, I've updated this question.
My requirements:
An overview map that has thousands of points and supports clustering.
A per location map that displays a single point
Ability a edit a single point location and integrate geocoding
Popups on all points
Consistent styling and features across all map variants
Nuxt app with SSR, so ability to block SSR on maps.
Given that maps will appear on different kinds of pages, there will be some code reuse.
In a VueJS/Nuxt environment, what are the pros and cons of using vue-mapbox, mapbox-gl-vue, or writing from scratch?