From c0d2e03591e0a4d130755e86fc14cac178c12b57 Mon Sep 17 00:00:00 2001 From: tkostuch Date: Wed, 6 Nov 2019 07:20:05 +0100 Subject: [PATCH 1/9] remove ref when use setItem in cache --- core/lib/store/storage.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/lib/store/storage.ts b/core/lib/store/storage.ts index e591731724..cb0e3ea96a 100644 --- a/core/lib/store/storage.ts +++ b/core/lib/store/storage.ts @@ -1,6 +1,7 @@ import * as localForage from 'localforage' import { Logger } from '@vue-storefront/core/lib/logger' import { isServer } from '@vue-storefront/core/helpers' +import cloneDeep from 'lodash-es/cloneDeep' const CACHE_TIMEOUT = 800 const CACHE_TIMEOUT_ITERATE = 2000 @@ -93,6 +94,7 @@ class LocalForageCacheDriver { _globalCache[dbName][collectionName] = {} } this._localCache = _globalCache[dbName][collectionName] + console.log(_globalCache) } this._collectionName = collectionName this._dbName = dbName @@ -291,7 +293,8 @@ class LocalForageCacheDriver { // saved, or something like that. public setItem (key, value, callback?, memoryOnly = false) { const isCallbackCallable = (typeof callback !== 'undefined' && callback) - this._localCache[key] = value + const copiedValue = cloneDeep(value) + this._localCache[key] = copiedValue if (memoryOnly) { return new Promise((resolve, reject) => { if (isCallbackCallable) callback(null, null) @@ -310,7 +313,7 @@ class LocalForageCacheDriver { }) } else { let isResolved = false - const promise = this._localForageCollection.ready().then(() => this._localForageCollection.setItem(key, value).then(result => { + const promise = this._localForageCollection.ready().then(() => this._localForageCollection.setItem(key, copiedValue).then(result => { if (isCallbackCallable) { callback(null, result) } From f2fd545a8ee882babc6e466c51b3fba757da70c7 Mon Sep 17 00:00:00 2001 From: tkostuch Date: Wed, 6 Nov 2019 08:25:44 +0100 Subject: [PATCH 2/9] clear timeouts in storage --- core/lib/store/storage.ts | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/core/lib/store/storage.ts b/core/lib/store/storage.ts index cb0e3ea96a..b281e7bb89 100644 --- a/core/lib/store/storage.ts +++ b/core/lib/store/storage.ts @@ -35,6 +35,12 @@ function roughSizeOfObject (object) { return bytes } +interface CacheTimeouts { + getItem: number, + iterate: number, + setItem: number +} + class LocalForageCacheDriver { private _collectionName: string; private _dbName: string; @@ -45,6 +51,11 @@ class LocalForageCacheDriver { private _useLocalCacheByDefault: boolean; private cacheErrorsCount: any; private _storageQuota: number; + private _cacheTimeouts: CacheTimeouts = { + getItem: null, + iterate: null, + setItem: null + } public constructor (collection, useLocalCacheByDefault = true, storageQuota = 0) { const collectionName = collection._config.storeName @@ -188,8 +199,8 @@ class LocalForageCacheDriver { Logger.error(err)() isResolved = true })) - - setTimeout(() => { + clearTimeout(this._cacheTimeouts.getItem) + this._cacheTimeouts.getItem = setTimeout(() => { if (!isResolved) { // this is cache time out check if (!this._persistenceErrorNotified) { Logger.error('Cache not responding for ' + key + '.', 'cache', { timeout: CACHE_TIMEOUT, errorsCount: this.cacheErrorsCount[this._collectionName] })() @@ -251,7 +262,8 @@ class LocalForageCacheDriver { if (isCallbackCallable) callback(err, null) } }) - setTimeout(() => { + clearTimeout(this._cacheTimeouts.iterate) + this._cacheTimeouts.iterate = setTimeout(() => { if (!isResolved) { // this is cache time out check if (!this._persistenceErrorNotified) { Logger.error('Cache not responding. (iterate)', 'cache', { timeout: CACHE_TIMEOUT, errorsCount: this.cacheErrorsCount[this._collectionName] })() @@ -323,7 +335,8 @@ class LocalForageCacheDriver { this._lastError = err throw err })) - setTimeout(() => { + clearTimeout(this._cacheTimeouts.iterate) + this._cacheTimeouts.setItem = setTimeout(() => { if (!isResolved) { // this is cache time out check if (!this._persistenceErrorNotified) { Logger.error('Cache not responding for ' + key + '.', 'cache', { timeout: CACHE_TIMEOUT, errorsCount: this.cacheErrorsCount[this._collectionName] })() From d2f4f7a4ad1dbed27e12865b37d20a1e23eb5768 Mon Sep 17 00:00:00 2001 From: tkostuch Date: Wed, 6 Nov 2019 10:15:38 +0100 Subject: [PATCH 3/9] return fresh object from cache and poc of nonReactive state --- core/lib/store/storage.ts | 37 ++++++++++++------- .../catalog-next/store/category/index.ts | 4 ++ .../catalog-next/store/category/mutations.ts | 5 ++- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/core/lib/store/storage.ts b/core/lib/store/storage.ts index b281e7bb89..4d0bd780ac 100644 --- a/core/lib/store/storage.ts +++ b/core/lib/store/storage.ts @@ -36,9 +36,10 @@ function roughSizeOfObject (object) { } interface CacheTimeouts { - getItem: number, - iterate: number, - setItem: number + getItem: any, + iterate: any, + setItem: any, + base: any } class LocalForageCacheDriver { @@ -54,7 +55,8 @@ class LocalForageCacheDriver { private _cacheTimeouts: CacheTimeouts = { getItem: null, iterate: null, - setItem: null + setItem: null, + base: null } public constructor (collection, useLocalCacheByDefault = true, storageQuota = 0) { @@ -66,7 +68,8 @@ class LocalForageCacheDriver { const storageQuota = this._storageQuota const iterateFnc = this.iterate.bind(this) const removeItemFnc = this.removeItem.bind(this) - setInterval(() => { + clearInterval(this._cacheTimeouts.base) + this._cacheTimeouts.base = setInterval(() => { let storageSize = 0 this.iterate((item, id, number) => { storageSize += roughSizeOfObject(item) @@ -105,7 +108,6 @@ class LocalForageCacheDriver { _globalCache[dbName][collectionName] = {} } this._localCache = _globalCache[dbName][collectionName] - console.log(_globalCache) } this._collectionName = collectionName this._dbName = dbName @@ -146,6 +148,10 @@ class LocalForageCacheDriver { return this._dbName } + public getLocalCache (key) { + return typeof this._localCache[key] !== 'undefined' ? cloneDeep(this._localCache[key]) : null + } + // Retrieve an item from the store. Unlike the original async_storage // library in Gaia, we don't modify return values at all. If a key's value // is `undefined`, we pass that value to the callback function. @@ -155,7 +161,7 @@ class LocalForageCacheDriver { if (this._useLocalCacheByDefault && this._localCache[key]) { // Logger.debug('Local cache fallback for GET', key)() return new Promise((resolve, reject) => { - const value = typeof this._localCache[key] !== 'undefined' ? this._localCache[key] : null + const value = this.getLocalCache(key) if (isCallbackCallable) callback(null, value) resolve(value) }) @@ -176,25 +182,27 @@ class LocalForageCacheDriver { // Logger.debug('No local cache fallback for GET', key)() const promise = this._localForageCollection.ready().then(() => this._localForageCollection.getItem(key).then(result => { const endTime = new Date().getTime() + const clonedResult = cloneDeep(result) if ((endTime - startTime) >= CACHE_TIMEOUT) { Logger.error('Cache promise resolved after [ms]' + key + (endTime - startTime))() } - if (!this._localCache[key] && result) { - this._localCache[key] = result // populate the local cache for the next call + if (!this._localCache[key] && clonedResult) { + this._localCache[key] = clonedResult // populate the local cache for the next call } if (!isResolved) { if (isCallbackCallable) { - callback(null, result) + callback(null, clonedResult) } isResolved = true } else { Logger.debug('Skipping return value as it was previously resolved')() } - return result + return clonedResult }).catch(err => { this._lastError = err if (!isResolved) { - if (isCallbackCallable) callback(null, typeof this._localCache[key] !== 'undefined' ? this._localCache[key] : null) + const value = this.getLocalCache(key) + if (isCallbackCallable) callback(null, value) } Logger.error(err)() isResolved = true @@ -208,14 +216,15 @@ class LocalForageCacheDriver { this.recreateDb() } this.cacheErrorsCount[this._collectionName] = this.cacheErrorsCount[this._collectionName] ? this.cacheErrorsCount[this._collectionName] + 1 : 1 - if (isCallbackCallable) callback(null, typeof this._localCache[key] !== 'undefined' ? this._localCache[key] : null) + const value = this.getLocalCache(key) + if (isCallbackCallable) callback(null, value) } }, CACHE_TIMEOUT) return promise } } else { return new Promise((resolve, reject) => { - const value = typeof this._localCache[key] !== 'undefined' ? this._localCache[key] : null + const value = this.getLocalCache(key) if (isCallbackCallable) callback(null, value) resolve(value) }) diff --git a/core/modules/catalog-next/store/category/index.ts b/core/modules/catalog-next/store/category/index.ts index c01fda5da1..8dd910ea1c 100644 --- a/core/modules/catalog-next/store/category/index.ts +++ b/core/modules/catalog-next/store/category/index.ts @@ -18,3 +18,7 @@ export const categoryModule: Module = { actions, mutations } + +export const nonReactiveState = { + products: [] +} diff --git a/core/modules/catalog-next/store/category/mutations.ts b/core/modules/catalog-next/store/category/mutations.ts index 802b74dee7..b921929395 100644 --- a/core/modules/catalog-next/store/category/mutations.ts +++ b/core/modules/catalog-next/store/category/mutations.ts @@ -3,10 +3,13 @@ import { MutationTree } from 'vuex' import * as types from './mutation-types' import CategoryState from './CategoryState' import { Category } from '../../types/Category' +import { nonReactiveState } from './index' +import cloneDeep from 'lodash-es/cloneDeep' const mutations: MutationTree = { [types.CATEGORY_SET_PRODUCTS] (state, products = []) { - state.products = products + nonReactiveState.products = cloneDeep(products) + state.products = products.map((product) => ({ ...product, configurable_children: product.configurable_children.map(child => child.sku) })) }, [types.CATEGORY_ADD_PRODUCTS] (state, products = []) { state.products.push(...products) From 8af150a5bc71f62909832cd4ef7e168a10a2de17 Mon Sep 17 00:00:00 2001 From: tkostuch Date: Wed, 6 Nov 2019 10:30:26 +0100 Subject: [PATCH 4/9] remove nonReactive state --- core/modules/catalog-next/store/category/index.ts | 4 ---- core/modules/catalog-next/store/category/mutations.ts | 5 +---- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/core/modules/catalog-next/store/category/index.ts b/core/modules/catalog-next/store/category/index.ts index 8dd910ea1c..c01fda5da1 100644 --- a/core/modules/catalog-next/store/category/index.ts +++ b/core/modules/catalog-next/store/category/index.ts @@ -18,7 +18,3 @@ export const categoryModule: Module = { actions, mutations } - -export const nonReactiveState = { - products: [] -} diff --git a/core/modules/catalog-next/store/category/mutations.ts b/core/modules/catalog-next/store/category/mutations.ts index b921929395..802b74dee7 100644 --- a/core/modules/catalog-next/store/category/mutations.ts +++ b/core/modules/catalog-next/store/category/mutations.ts @@ -3,13 +3,10 @@ import { MutationTree } from 'vuex' import * as types from './mutation-types' import CategoryState from './CategoryState' import { Category } from '../../types/Category' -import { nonReactiveState } from './index' -import cloneDeep from 'lodash-es/cloneDeep' const mutations: MutationTree = { [types.CATEGORY_SET_PRODUCTS] (state, products = []) { - nonReactiveState.products = cloneDeep(products) - state.products = products.map((product) => ({ ...product, configurable_children: product.configurable_children.map(child => child.sku) })) + state.products = products }, [types.CATEGORY_ADD_PRODUCTS] (state, products = []) { state.products.push(...products) From b7f24fc12e60486c22a4725aeaed09b1635a5a30 Mon Sep 17 00:00:00 2001 From: tkostuch Date: Wed, 6 Nov 2019 10:54:01 +0100 Subject: [PATCH 5/9] remove reference in observe-visibility --- .../default-amp/components/core/ProductTile.vue | 8 +++++--- src/themes/default/components/core/ProductTile.vue | 12 +++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/themes/default-amp/components/core/ProductTile.vue b/src/themes/default-amp/components/core/ProductTile.vue index deb9dbde2d..1f86b2a496 100755 --- a/src/themes/default-amp/components/core/ProductTile.vue +++ b/src/themes/default-amp/components/core/ProductTile.vue @@ -52,6 +52,7 @@ import rootStore from '@vue-storefront/core/store' import { ProductTile } from '@vue-storefront/core/modules/catalog/components/ProductTile.ts' import config from 'config' +import cloneDeep from 'lodash-es/cloneDeep' export default { mixins: [ProductTile], @@ -72,11 +73,12 @@ export default { } }, visibilityChanged (isVisible, entry) { + const product = cloneDeep(this.product) if (isVisible) { if (config.products.configurableChildrenStockPrefetchDynamic && config.products.filterUnavailableVariants) { - const skus = [this.product.sku] - if (this.product.type_id === 'configurable' && this.product.configurable_children && this.product.configurable_children.length > 0) { - for (const confChild of this.product.configurable_children) { + const skus = [product.sku] + if (product.type_id === 'configurable' && product.configurable_children && product.configurable_children.length > 0) { + for (const confChild of product.configurable_children) { const cachedItem = rootStore.state.stock.cache[confChild.id] if (typeof cachedItem === 'undefined' || cachedItem === null) { skus.push(confChild.sku) diff --git a/src/themes/default/components/core/ProductTile.vue b/src/themes/default/components/core/ProductTile.vue index 7f931c0a39..c87b7ad7e7 100644 --- a/src/themes/default/components/core/ProductTile.vue +++ b/src/themes/default/components/core/ProductTile.vue @@ -69,6 +69,7 @@ import AddToWishlist from 'theme/components/core/blocks/Wishlist/AddToWishlist' import AddToCompare from 'theme/components/core/blocks/Compare/AddToCompare' import { IsOnWishlist } from '@vue-storefront/core/modules/wishlist/components/IsOnWishlist' import { IsOnCompare } from '@vue-storefront/core/modules/compare/components/IsOnCompare' +import cloneDeep from 'lodash-es/cloneDeep' export default { mixins: [ProductTile, IsOnWishlist, IsOnCompare], @@ -105,16 +106,17 @@ export default { } }, visibilityChanged (isVisible, entry) { + const product = cloneDeep(this.product) if ( isVisible && config.products.configurableChildrenStockPrefetchDynamic && config.products.filterUnavailableVariants && - this.product.type_id === 'configurable' && - this.product.configurable_children && - this.product.configurable_children.length > 0 + product.type_id === 'configurable' && + product.configurable_children && + product.configurable_children.length > 0 ) { - const skus = [this.product.sku] - for (const confChild of this.product.configurable_children) { + const skus = [product.sku] + for (const confChild of product.configurable_children) { const cachedItem = rootStore.state.stock.cache[confChild.id] if (typeof cachedItem === 'undefined' || cachedItem === null) { skus.push(confChild.sku) From c329db86b477c6a8a0c316beb23d2439ad219747 Mon Sep 17 00:00:00 2001 From: tkostuch Date: Wed, 6 Nov 2019 11:24:22 +0100 Subject: [PATCH 6/9] use non reactive state --- core/modules/catalog-next/store/category/getters.ts | 11 ++++++++++- core/modules/catalog-next/store/category/index.ts | 4 ++++ .../modules/catalog-next/store/category/mutations.ts | 5 ++++- .../default-amp/components/core/ProductTile.vue | 8 +++----- src/themes/default/components/core/ProductTile.vue | 12 +++++------- 5 files changed, 26 insertions(+), 14 deletions(-) diff --git a/core/modules/catalog-next/store/category/getters.ts b/core/modules/catalog-next/store/category/getters.ts index 9cff3f2ca5..9b537f9954 100644 --- a/core/modules/catalog-next/store/category/getters.ts +++ b/core/modules/catalog-next/store/category/getters.ts @@ -1,3 +1,4 @@ +import { nonReactiveState } from './index'; import { GetterTree } from 'vuex' import RootState from '@vue-storefront/core/types/RootState' import CategoryState from './CategoryState' @@ -13,12 +14,20 @@ import { Category } from '../../types/Category' import { parseCategoryPath } from '@vue-storefront/core/modules/breadcrumbs/helpers' import { _prepareCategoryPathIds, getSearchOptionsFromRouteParams } from '../../helpers/categoryHelpers'; import { removeStoreCodeFromRoute } from '@vue-storefront/core/lib/multistore' +import cloneDeep from 'lodash-es/cloneDeep' + +function mapCategoryProducts (productsSkus, productsData) { + return productsSkus.map(prodSku => { + const product = productsData.find(prodData => prodData.sku === prodSku) + return cloneDeep(product) + }) +} const getters: GetterTree = { getCategories: (state): Category[] => Object.values(state.categoriesMap), getCategoriesMap: (state): { [id: string]: Category} => state.categoriesMap, getNotFoundCategoryIds: (state): string[] => state.notFoundCategoryIds, - getCategoryProducts: (state) => state.products, + getCategoryProducts: (state) => mapCategoryProducts(state.products, nonReactiveState.products), getCategoryFrom: (state, getters) => (path: string = '') => { return getters.getCategories.find(category => (removeStoreCodeFromRoute(path) as string).replace(/^(\/)/gm, '') === category.url_path) }, diff --git a/core/modules/catalog-next/store/category/index.ts b/core/modules/catalog-next/store/category/index.ts index c01fda5da1..8dd910ea1c 100644 --- a/core/modules/catalog-next/store/category/index.ts +++ b/core/modules/catalog-next/store/category/index.ts @@ -18,3 +18,7 @@ export const categoryModule: Module = { actions, mutations } + +export const nonReactiveState = { + products: [] +} diff --git a/core/modules/catalog-next/store/category/mutations.ts b/core/modules/catalog-next/store/category/mutations.ts index 802b74dee7..d31e527240 100644 --- a/core/modules/catalog-next/store/category/mutations.ts +++ b/core/modules/catalog-next/store/category/mutations.ts @@ -1,12 +1,15 @@ +import { nonReactiveState } from './index'; import Vue from 'vue' import { MutationTree } from 'vuex' import * as types from './mutation-types' import CategoryState from './CategoryState' import { Category } from '../../types/Category' +import cloneDeep from 'lodash-es/cloneDeep' const mutations: MutationTree = { [types.CATEGORY_SET_PRODUCTS] (state, products = []) { - state.products = products + nonReactiveState.products = cloneDeep(products) + state.products = cloneDeep(products).map(prod => prod.sku) }, [types.CATEGORY_ADD_PRODUCTS] (state, products = []) { state.products.push(...products) diff --git a/src/themes/default-amp/components/core/ProductTile.vue b/src/themes/default-amp/components/core/ProductTile.vue index 1f86b2a496..deb9dbde2d 100755 --- a/src/themes/default-amp/components/core/ProductTile.vue +++ b/src/themes/default-amp/components/core/ProductTile.vue @@ -52,7 +52,6 @@ import rootStore from '@vue-storefront/core/store' import { ProductTile } from '@vue-storefront/core/modules/catalog/components/ProductTile.ts' import config from 'config' -import cloneDeep from 'lodash-es/cloneDeep' export default { mixins: [ProductTile], @@ -73,12 +72,11 @@ export default { } }, visibilityChanged (isVisible, entry) { - const product = cloneDeep(this.product) if (isVisible) { if (config.products.configurableChildrenStockPrefetchDynamic && config.products.filterUnavailableVariants) { - const skus = [product.sku] - if (product.type_id === 'configurable' && product.configurable_children && product.configurable_children.length > 0) { - for (const confChild of product.configurable_children) { + const skus = [this.product.sku] + if (this.product.type_id === 'configurable' && this.product.configurable_children && this.product.configurable_children.length > 0) { + for (const confChild of this.product.configurable_children) { const cachedItem = rootStore.state.stock.cache[confChild.id] if (typeof cachedItem === 'undefined' || cachedItem === null) { skus.push(confChild.sku) diff --git a/src/themes/default/components/core/ProductTile.vue b/src/themes/default/components/core/ProductTile.vue index c87b7ad7e7..7f931c0a39 100644 --- a/src/themes/default/components/core/ProductTile.vue +++ b/src/themes/default/components/core/ProductTile.vue @@ -69,7 +69,6 @@ import AddToWishlist from 'theme/components/core/blocks/Wishlist/AddToWishlist' import AddToCompare from 'theme/components/core/blocks/Compare/AddToCompare' import { IsOnWishlist } from '@vue-storefront/core/modules/wishlist/components/IsOnWishlist' import { IsOnCompare } from '@vue-storefront/core/modules/compare/components/IsOnCompare' -import cloneDeep from 'lodash-es/cloneDeep' export default { mixins: [ProductTile, IsOnWishlist, IsOnCompare], @@ -106,17 +105,16 @@ export default { } }, visibilityChanged (isVisible, entry) { - const product = cloneDeep(this.product) if ( isVisible && config.products.configurableChildrenStockPrefetchDynamic && config.products.filterUnavailableVariants && - product.type_id === 'configurable' && - product.configurable_children && - product.configurable_children.length > 0 + this.product.type_id === 'configurable' && + this.product.configurable_children && + this.product.configurable_children.length > 0 ) { - const skus = [product.sku] - for (const confChild of product.configurable_children) { + const skus = [this.product.sku] + for (const confChild of this.product.configurable_children) { const cachedItem = rootStore.state.stock.cache[confChild.id] if (typeof cachedItem === 'undefined' || cachedItem === null) { skus.push(confChild.sku) From d96428369ba14196f0b1ac7759bcfa19cdd5c95d Mon Sep 17 00:00:00 2001 From: tkostuch Date: Fri, 8 Nov 2019 07:03:05 +0100 Subject: [PATCH 7/9] update inspect prod --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a007fa378f..51b43249f4 100755 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "static-server": "cross-env TS_NODE_PROJECT=\"tsconfig-build.json\" ts-node ./core/scripts/static-server.ts", "generate": "cross-env TS_NODE_PROJECT=\"tsconfig-build.json\" ts-node ./core/scripts/generate.ts", "start": "cross-env NODE_ENV=production TS_NODE_PROJECT=\"tsconfig-build.json\" pm2 start ecosystem.json $PM2_ARGS", - "start:inspect": "cross-env NODE_ENV=production TS_NODE_PROJECT=\"tsconfig-build.json\" node --inspect ./core/scripts/server.js", + "start:inspect": "cross-env NODE_ENV=production TS_NODE_PROJECT=\"tsconfig-build.json\" node --inspect -r ts-node/register ./core/scripts/server", "installer": "node ./core/scripts/installer", "installer:ci": "yarn installer --default-config", "all": "cross-env NODE_ENV=development node ./core/scripts/all", From 8ea7f81f0cb374c70eec7d4979a2368cd96af2b2 Mon Sep 17 00:00:00 2001 From: tkostuch Date: Wed, 13 Nov 2019 08:44:46 +0100 Subject: [PATCH 8/9] clear server reference from requests --- core/app.ts | 15 ++++++++++----- core/client-entry.ts | 2 +- core/filters/price.js | 3 +++ core/modules/catalog/helpers/search.ts | 4 ++-- core/modules/catalog/store/category/actions.ts | 4 ++-- core/scripts/server.ts | 3 +++ core/scripts/utils/ssr-renderer.js | 11 +++++++++-- core/server-entry.ts | 1 - 8 files changed, 30 insertions(+), 13 deletions(-) diff --git a/core/app.ts b/core/app.ts index 163c7a51dd..0cde365b6e 100755 --- a/core/app.ts +++ b/core/app.ts @@ -47,7 +47,12 @@ const createApp = async (ssrContext, config, storeCode = null): Promise<{app: Vu store.state.version = process.env.APPVERSION store.state.config = config // @deprecated store.state.__DEMO_MODE__ = (config.demomode === true) - if (ssrContext) Vue.prototype.$ssrRequestContext = ssrContext + if (ssrContext) { + // @deprecated - we shouldn't share server context between requests + Vue.prototype.$ssrRequestContext = {output: {cacheTags: ssrContext.output.cacheTags}} + + Vue.prototype.$cacheTags = ssrContext.output.cacheTags + } if (!store.state.config) store.state.config = globalConfig // @deprecated - we should avoid the `config` const storeView = await prepareStoreView(storeCode) // prepare the default storeView store.state.storeView = storeView @@ -66,6 +71,10 @@ const createApp = async (ssrContext, config, storeCode = null): Promise<{app: Vu Object.keys(coreMixins).forEach(key => { Vue.mixin(coreMixins[key]) }) + + Object.keys(coreFilters).forEach(key => { + Vue.filter(key, coreFilters[key]) + }) }) // @todo remove this part when we'll get rid of global multistore mixin @@ -78,10 +87,6 @@ const createApp = async (ssrContext, config, storeCode = null): Promise<{app: Vu }) } - Object.keys(coreFilters).forEach(key => { - Vue.filter(key, coreFilters[key]) - }) - let vueOptions = { router: routerProxy, store, diff --git a/core/client-entry.ts b/core/client-entry.ts index 037d6f84c9..3fe088d2a1 100755 --- a/core/client-entry.ts +++ b/core/client-entry.ts @@ -82,7 +82,7 @@ const invokeClientEntry = async () => { } return next() // do not resolve asyncData on server render - already been done } - if (Vue.prototype.$ssrRequestContext) Vue.prototype.$ssrRequestContext.output.cacheTags = new Set() + if (!Vue.prototype.$cacheTags) Vue.prototype.$cacheTags = new Set() const matched = router.getMatchedComponents(to) if (to) { // this is from url if (globalConfig.storeViews.multistore === true) { diff --git a/core/filters/price.js b/core/filters/price.js index eda9d596ae..c69462fb41 100644 --- a/core/filters/price.js +++ b/core/filters/price.js @@ -18,6 +18,9 @@ export function price (value) { return value; } const storeView = currentStoreView(); + if (!storeView.i18n) { + return value; + } const { defaultLocale, currencySign, priceFormat } = storeView.i18n const formattedValue = formatValue(value, defaultLocale); diff --git a/core/modules/catalog/helpers/search.ts b/core/modules/catalog/helpers/search.ts index 07089ef776..c35d70c8b9 100644 --- a/core/modules/catalog/helpers/search.ts +++ b/core/modules/catalog/helpers/search.ts @@ -57,7 +57,7 @@ export const storeProductToCache = (product, cacheByKey) => { }; export const preConfigureProduct = ({ product, populateRequestCacheTags }) => { - const shouldPopulateCacheTags = populateRequestCacheTags && Vue.prototype.$ssrRequestContext; + const shouldPopulateCacheTags = populateRequestCacheTags && Vue.prototype.$cacheTags; const isFirstVariantAsDefaultInURL = config.products.setFirstVarianAsDefaultInURL && product.hasOwnProperty('configurable_children') && @@ -66,7 +66,7 @@ export const preConfigureProduct = ({ product, populateRequestCacheTags }) => { product.info = {}; if (shouldPopulateCacheTags) { - Vue.prototype.$ssrRequestContext.output.cacheTags.add(`P${product.id}`); + Vue.prototype.$cacheTags.add(`P${product.id}`); } if (!product.parentSku) { diff --git a/core/modules/catalog/store/category/actions.ts b/core/modules/catalog/store/category/actions.ts index d1f0cd8f70..ea228e6476 100644 --- a/core/modules/catalog/store/category/actions.ts +++ b/core/modules/catalog/store/category/actions.ts @@ -119,8 +119,8 @@ const actions: ActionTree = { if (setCurrentCategory) { commit(types.CATEGORY_UPD_CURRENT_CATEGORY, mainCategory) } - if (populateRequestCacheTags && mainCategory && Vue.prototype.$ssrRequestContext) { - Vue.prototype.$ssrRequestContext.output.cacheTags.add(`C${mainCategory.id}`) + if (populateRequestCacheTags && mainCategory && Vue.prototype.$cacheTags) { + Vue.prototype.$cacheTags.add(`C${mainCategory.id}`) } if (setCurrentCategoryPath) { let currentPath = [] diff --git a/core/scripts/server.ts b/core/scripts/server.ts index c6652e60b8..5c491c5203 100755 --- a/core/scripts/server.ts +++ b/core/scripts/server.ts @@ -228,6 +228,9 @@ app.get('*', (req, res, next) => { console.log(`whole request [${req.url}]: ${Date.now() - s}ms`) next() }).catch(errorHandler) + .finally(() => { + ssr.clearContext(context) + }) } const dynamicCacheHandler = () => { diff --git a/core/scripts/utils/ssr-renderer.js b/core/scripts/utils/ssr-renderer.js index 4e1def36e3..d5b3e61b29 100644 --- a/core/scripts/utils/ssr-renderer.js +++ b/core/scripts/utils/ssr-renderer.js @@ -97,7 +97,7 @@ function initSSRRequestContext (app, req, res, config) { filter: (output, context) => { return output }, appendHead: (context) => { return ''; }, template: 'default', - cacheTags: null + cacheTags: new Set() }, server: { app: app, @@ -112,10 +112,17 @@ function initSSRRequestContext (app, req, res, config) { }; } +function clearContext (context) { + Object.keys(context.server).forEach(key => delete context.server[key]) + delete context.output['cacheTags'] + delete context['meta'] +} + module.exports = { createRenderer, initTemplatesCache, initSSRRequestContext, applyAdvancedOutputProcessing, - compileTemplate: compile + compileTemplate: compile, + clearContext } diff --git a/core/server-entry.ts b/core/server-entry.ts index 7c4c5364e4..530bef6ec1 100755 --- a/core/server-entry.ts +++ b/core/server-entry.ts @@ -70,7 +70,6 @@ export default async context => { RouterManager.flushRouteQueue() context.initialState = initialState return new Promise((resolve, reject) => { - context.output.cacheTags = new Set() const meta = (app as any).$meta() router.push(context.url) context.meta = meta From 5b8bcd1e69fb12ba9fdb378edacac6d2b248a51e Mon Sep 17 00:00:00 2001 From: tkostuch Date: Wed, 13 Nov 2019 10:29:12 +0100 Subject: [PATCH 9/9] check if cacheTags is not empty --- core/scripts/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/scripts/server.ts b/core/scripts/server.ts index 5c491c5203..1f4b1be3ac 100755 --- a/core/scripts/server.ts +++ b/core/scripts/server.ts @@ -179,7 +179,7 @@ app.get('*', (req, res, next) => { res.setHeader('Content-Type', 'text/html') } let tagsArray = [] - if (config.server.useOutputCacheTagging && context.output.cacheTags !== null) { + if (config.server.useOutputCacheTagging && context.output.cacheTags && context.output.cacheTags.size > 0) { tagsArray = Array.from(context.output.cacheTags) const cacheTags = tagsArray.join(' ') res.setHeader('X-VS-Cache-Tags', cacheTags)