Repository: vue
Issue: Computed properties can have widely different performance characteristics on client and server (because they are not cached during SSR)
Labels: discussion,feat:ssr

### Version
[`v2.4.3`](https://github.com/vuejs/vue/releases/tag/v2.4.3) - current ([`v2.6.10`](https://github.com/vuejs/vue/releases/tag/v2.6.10))

### Reproduction link
[https://jsfiddle.net/anc6Lf23/2/](https://jsfiddle.net/anc6Lf23/2/)

### Steps to reproduce
1. Open the JSFiddle
2. You will see the time it takes to compute a value without caching of computed properties (~1 second) in the output
3. Set "CACHE = true" in the first line of the JS part to see the time it takes to compute the value with caching (~2 ms)

This issue concerns SSR but for simplicity I created the fiddle which emulates the behavior of the server render:
- `CACHE = true` – the behavior we usually have in the client
- `CACHE = false` – the behavior during SSR

### What is expected?
I would expect computed properties to have comparable performance characteristics on the server and client, so that I don't need to write custom code. 
I.e. I would expect computed properties to be cached during SSR.

### What is actually happening?
Computed properties are not cached and therefore have drastically different performance characteristics in some cases.

---
### Description if the issue

Since [computed properties are not cached during SSR](https://ssr.vuejs.org/guide/universal.html#component-lifecycle-hooks) some components unexpectedly take significantly longer to render. This is the case if it is heavy to compute the property or if it is accessed a lot. 

I would usually expect a computed property to have constant time complexity (`O(1)`) no matter how often we access it. But on the server it suddenly becomes linear time complexity (`O(n)`). This is especially critical when the computed is accessed in a loop. When we have multiple computed properties relaying on each other, each containing loops, this gets *really* bad. Then it has polynomial time with the exponent being the amount of nested computed properties (E.g. `O(n^3)` for three levels of computes, like in the JSFiddle)

### Real world example

I noticed this issue because our server renderer suddenly took multiple seconds (5-8 seconds) to respond after enabling a new component for SSR. Normally rendering the app on the server takes about 100ms.

The effected component is part of a proprietary code base but it is similar to the one in the JSFiddle. You can see the component in production here: 
- Open: https://www.ikea.com/de/de/bereiche/wohnzimmer/
- Click on the "Serien" button
- The flyout content is the effected component 

After finding out about this I also investigated other occurrences of this: 
In our Vuex store we did not have any nested getters with loops, like described above, however some of the getters are somewhat heavy to compute (~1ms) and accessed a lot in various templates. So I decided to introduce a very simple custom caching layer to our store. This sped up server rendering by about 20%.

**This could also be a low hanging fruit for optimizing SSR performance:**
Based on analyzing our own app, I would roughly estimate that caching all computed properties could speed up server rendering by about 30% in an average Vue.js app.

For me this issue was hard to understand because the affected code seemed harmless at first.

### Mitigation

To mitigate this issue you can move access to computes out of loops: access them once, store them in a local variable and then use this variable in the loop. This is generally a good idea since any look up of a property on a Vue.js VM has a small cost.  

However this is not possible if you have a loop inside your templates.

### References

- The code that controls this behavior:
https://github.com/vuejs/vue/blob/0948d999f2fddf9f90991956493f976273c5da1f/src/core/instance/state.js#L208-L219

- The issue that lead to this behavior being introduced: vuejs/vuex#877

- The commit that introduced this behavior 06741f32

- Earlier occasion of someone stumbling over this: 
  - nuxt/nuxt.js#2447
  - https://forum.vuejs.org/t/ssr-performance-problems-due-to-lack-of-caching/24653/5

<!-- generated by vue-issues. DO NOT REMOVE -->