From 8a90913e57f269236e315832f54766d071e9961b Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 1 Sep 2017 12:51:29 -0400 Subject: [PATCH] fix: computed properties should not be cached during SSR ref: vuejs/vuex#877 --- src/core/instance/state.js | 28 +++++++++++++++++++++++----- test/ssr/ssr-string.spec.js | 21 +++++++++++++++++++-- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/core/instance/state.js b/src/core/instance/state.js index bbe7f882984..749aafcddb9 100644 --- a/src/core/instance/state.js +++ b/src/core/instance/state.js @@ -23,6 +23,7 @@ import { nativeWatch, validateProp, isPlainObject, + isServerRendering, isReservedAttribute } from '../util/index' @@ -169,6 +170,8 @@ const computedWatcherOptions = { lazy: true } function initComputed (vm: Component, computed: Object) { process.env.NODE_ENV !== 'production' && checkOptionType(vm, 'computed') const watchers = vm._computedWatchers = Object.create(null) + // computed properties are just getters during SSR + const isSSR = isServerRendering() for (const key in computed) { const userDef = computed[key] @@ -179,8 +182,16 @@ function initComputed (vm: Component, computed: Object) { vm ) } - // create internal watcher for the computed property. - watchers[key] = new Watcher(vm, getter || noop, noop, computedWatcherOptions) + + if (!isSSR) { + // create internal watcher for the computed property. + watchers[key] = new Watcher( + vm, + getter || noop, + noop, + computedWatcherOptions + ) + } // component-defined computed properties are already defined on the // component prototype. We only need to define computed properties defined @@ -197,13 +208,20 @@ function initComputed (vm: Component, computed: Object) { } } -export function defineComputed (target: any, key: string, userDef: Object | Function) { +export function defineComputed ( + target: any, + key: string, + userDef: Object | Function +) { + const shouldCache = !isServerRendering() if (typeof userDef === 'function') { - sharedPropertyDefinition.get = createComputedGetter(key) + sharedPropertyDefinition.get = shouldCache + ? createComputedGetter(key) + : userDef sharedPropertyDefinition.set = noop } else { sharedPropertyDefinition.get = userDef.get - ? userDef.cache !== false + ? shouldCache && userDef.cache !== false ? createComputedGetter(key) : userDef.get : noop diff --git a/test/ssr/ssr-string.spec.js b/test/ssr/ssr-string.spec.js index d9c330004e1..75de1bbaaef 100644 --- a/test/ssr/ssr-string.spec.js +++ b/test/ssr/ssr-string.spec.js @@ -909,13 +909,30 @@ describe('SSR: renderToString', () => { }) it('should escape static strings', done => { - renderVmWithOptions(({ + renderVmWithOptions({ template: `
<foo>
` - }), res => { + }, res => { expect(res).toBe(`
<foo>
`) done() }) }) + + it('should not cache computed properties', done => { + renderVmWithOptions({ + template: `
{{ foo }}
`, + data: () => ({ bar: 1 }), + computed: { + foo () { return this.bar + 1 } + }, + created () { + this.foo // access + this.bar++ // trigger change + } + }, res => { + expect(res).toBe(`
3
`) + done() + }) + }) }) function renderVmWithOptions (options, cb) {