Inherit storeview config after base settings in multistore mode
See original GitHub issueSummary
In multistore mode with multiple storeviews on one instance, the config becomes hard to maintain and there are lots of duplications. We need a mechanism settings inheritance from base storeview to child ones. We can either create another storeview which won’t be mapped to an url and point other storeviews to inherit its settings or copy settings from default storeview.
Motivation
Multistore setup with many storeviews has lots of duplicated settings that could be inherited to improve maintainability.
Guide-level explanation
The old way we’re configuring multistore setup is as follows:
"defaultStoreCode": "",
"storeViews": {
"multistore": true,
"commonCache": true,
"mapStoreUrlsFor": ["de", "it"],
"de": {
"storeCode": "de",
"disabled": false,
"storeId": 3,
"name": "German Store",
"url": "/de",
"appendStoreCode": true,
"elasticsearch": {
"host": "/api/catalog",
"index": "vue_storefront_catalog_de"
},
"tax": {
"sourcePriceIncludesTax": false,
"defaultCountry": "DE",
"defaultRegion": "",
"calculateServerSide": true
},
"i18n": {
"fullCountryName": "Germany",
"fullLanguageName": "German",
"defaultLanguage": "DE",
"defaultCountry": "DE",
"defaultLocale": "de-DE",
"currencyCode": "EUR",
"currencySign": "EUR",
"dateFormat": "HH:mm D-M-YYYY"
}
},
"it": {
"storeCode": "it",
"disabled": false,
"storeId": 4,
"name": "Italian Store",
"url": "/it",
"appendStoreCode": true,
"elasticsearch": {
"host": "/api/catalog",
"index": "vue_storefront_catalog_it"
},
"tax": {
"sourcePriceIncludesTax": false,
"defaultCountry": "IT",
"defaultRegion": "",
"calculateServerSide": true
},
"i18n": {
"fullCountryName": "Italy",
"fullLanguageName": "Italian",
"defaultCountry": "IT",
"defaultLanguage": "IT",
"defaultLocale": "it-IT",
"currencyCode": "EUR",
"currencySign": "EUR",
"dateFormat": "HH:mm D-M-YYYY"
}
}
As you can see, there are multiple fields that are having duplicated values across all multistores. Inheriting these settings from base settings would definitely shorten that up.
Approach 1.
We can copy all settings from default storeview which currently acts as a fallback to US storeview. Below there is a configuration for two storeviews and it’s already long. Imagine how would it look with 10 storeviews that share similar language and tax settings but different product sets.
"defaultStoreCode": "",
"storeViews": {
"multistore": true,
"commonCache": true,
"mapStoreUrlsFor": ["de", "it"],
"de": {
"storeCode": "de",
"storeId": 3,
"name": "German Store",
"url": "/de",
"elasticsearch": {
"index": "vue_storefront_catalog_de"
},
"tax": {
"defaultCountry": "DE"
},
"i18n": {
"fullCountryName": "Germany",
"fullLanguageName": "German",
"defaultLanguage": "DE",
"defaultCountry": "DE",
"defaultLocale": "de-DE"
}
},
"it": {
"storeCode": "it",
"storeId": 4,
"name": "Italian Store",
"url": "/it",
"elasticsearch": {
"index": "vue_storefront_catalog_it"
},
"tax": {
"defaultCountry": "IT"
},
"i18n": {
"fullCountryName": "Italy",
"fullLanguageName": "Italian",
"defaultCountry": "IT",
"defaultLanguage": "IT",
"defaultLocale": "it-IT"
}
}
Approach 2.
We could create a base, unmapped storeview to inherit all the settings from
"defaultStoreCode": "",
"storeViews": {
"multistore": true,
"commonCache": true,
"mapStoreUrlsFor": ["de", "it"],
"base": {
"disabled": false,
"appendStoreCode": true,
"elasticsearch": {
"host": "/api/catalog",
},
"tax": {
"sourcePriceIncludesTax": false,
"defaultRegion": "",
"calculateServerSide": true
},
"i18n": {
"currencyCode": "EUR",
"currencySign": "EUR",
"dateFormat": "HH:mm D-M-YYYY"
}
},
"de": {
"inherit": "base",
"storeCode": "de",
"storeId": 3,
"name": "German Store",
"url": "/de",
"elasticsearch": {
"index": "vue_storefront_catalog_de"
},
"tax": {
"defaultCountry": "DE"
},
"i18n": {
"fullCountryName": "Germany",
"fullLanguageName": "German",
"defaultLanguage": "DE",
"defaultCountry": "DE",
"defaultLocale": "de-DE"
}
},
"it": {
"inherit": "base",
"storeCode": "it",
"storeId": 4,
"name": "Italian Store",
"url": "/it",
"elasticsearch": {
"index": "vue_storefront_catalog_it"
},
"tax": {
"defaultCountry": "IT"
},
"i18n": {
"fullCountryName": "Italy",
"fullLanguageName": "Italian",
"defaultCountry": "IT",
"defaultLanguage": "IT",
"defaultLocale": "it-IT"
}
}
Reference-level explanation
Approach 1.1.
In every config to read values, we need to use storeViewConfig.value || defaultStoreViewConfig.value
. A very ugly way in my opinion but still should be mentioned for the record, I guess.
Approach 1.2.
We need to merge every storeview config with default storeview values spread across the config file on app startup and every config dynamic reload.
Approach 1.3.
We need to merge resolved storeview config with default storeview values spread across the config file in https://github.com/DivanteLtd/vue-storefront/blob/3908344ddff34c2505af4123c5eeaeff64b1b46b/core/lib/multistore.ts#L52
Approach 2.1
Same as in 1.2 but this time we need to deep merge two storeview configs (base and target one).
Approach 2.2
Same as in 1.3. but this time we need to deep merge two storeview configs (base and target one).
Drawbacks
- additional complication of loading config values
Unanswered questions:
- Do we allow nested inheritance in approach 2.*? It may lead to creating more complicated and unmaintainable configs than the current approach if abused (used wrongly).
Rationale and alternatives
Keeping it as it is or using a separate tool to hydrate config with appropriate variables (e.g. ansible, environmental variables).
Issue Analytics
- State:
- Created 4 years ago
- Comments:7 (5 by maintainers)
Top GitHub Comments
I’ve also added loading fallback values from storeview scoped configs to default config so now the default config is global ans used everywhere unless overriden in a storeview scoped config.
Now we have a mix of 1.3 and 2.2
I’ve decided to create a PR accordingly to the 2.2. approach. Please take a look. If you like it we can merge that and call it a day 😃