vue-storefront-1
vue-storefront-1 copied to clipboard
Optional defaultStoreCode in url for multistore
What is the motivation for adding / enhancing this feature?
It would be very useful if there could be a configuration option to have VSF keep the store code/url key of the default store in the URL. At the moment the defaultStoreCode is not included in the url and it just loads the store without it. However, in some multistore situations it makes more sense to have the storecode/url key always in the url, even for the default store.
See https://forum.vuestorefront.io/t/handling-defaultstorecode-for-multi-store/564 for discussion.
What are the acceptance criteria
Browsing to mydomain.tld will redirect users to mydomain.tld/{default-store} if this ability is enabled.
Can you complete this feature request by yourself?
- [ ] YES
- [x] NO
At the moment I'm not able to commit to this, but could get to it later on if it hasn't been completed.
Which Release Cycle state this refers to? Info for developer.
Pick one option.
- [x] This is a normal feature request. This should be available on https://test.storefrontcloud.io and then after tests this can be added to next Vue Storefront version. In this case Developer should create branch from
developbranch and create Pull Request2. Feature / Improvementback todevelop. - [ ] (Pick this option only if you're sure) This is an important improvement request for current Release Candidate version on https://next.storefrontcloud.io and should be placed in next RC version. In this case Developer should create branch from
releasebranch and create Pull Request3. Stabilisation fixback torelease. - [ ] (Pick this option only if you're sure) This is a critical improvement request for current Stable version on https://demo.storefrontcloud.io and should be placed in next stable version. In this case Developer should create branch from
hotfixormasterbranch and create Pull Request4. Hotfixback tohotfix.
Additional information
I solved it by adding a second store, like which inherits from my desired default one.
For example:
I'm having a german store config which I wan't to be the default store.
So in best case the default store should also be available in http://localhost/specific/url and http://localhost/de/specific/url – so both is the /de store.
My solution would be to use the extend flag to extend from the default store ore visa versa to achieve this like:
{
"defaultStoreCode": "default",
"storeViews": {
"mapStoreUrlsFor": ["de", "fr", "uk", "it"],
"default": {
"storeCode": "default",
"storeId": 1,
"name": "German Store",
"url": "/",
"appendStoreCode": false,
"disabled": false,
"elasticsearch": {
"host": "/api/catalog",
"index": "vue_storefront_catalog_1"
},
"tax": {
"sourcePriceIncludesTax": false,
"defaultCountry": "DE",
"defaultRegion": "",
"calculateServerSide": true
}
},
"de": {
"extend": "default",
"storeCode": "de",
"storeId": 1,
"appendStoreCode": true,
"disabled": false,
"elasticsearch": {
"host": "/api/catalog",
"index": "vue_storefront_catalog_1"
}
},
"fr": {
"extend": "de",
"storeCode": "fr",
"storeId": 12,
"name": "French Store",
"url": "/fr",
"appendStoreCode": true,
"disabled": false,
"elasticsearch": {
"index": "vue_storefront_catalog_12"
},
"tax": {
"defaultCountry": "FR"
},
"i18n": {
"fullCountryName": "France",
"fullLanguageName": "French",
"defaultLanguage": "FR",
"defaultCountry": "FR",
"defaultLocale": "fr-FR"
}
},
...
},
"i18n": {
"defaultCountry": "DE",
"defaultLanguage": "DE",
"availableLocale": ["en-GB","de-DE","fr-FR","it-IT"],
"defaultLocale": "de-DE",
"currencyCode": "EUR",
"currencySign": "€",
"currencySignPlacement": "append",
"dateFormat": "HH:mm D.M.YYYY",
"fullCountryName": "Germany",
"fullLanguageName": "German",
"bundleAllStoreviewLanguages": true
},
...
}
In fact extending the configs isn't working totally smooth yet, like "appendStoreCode": true has to be on each node, etc. – but it is working for us at the moment and leaves a lot of flexibility without changing the code at the core.
Claiming this issue for today's Hackathon. Working on it with @khako
If somebody is still looking for this: I implemented it using a server hook inside a new module (like in robots module with the server.ts) to add a new ExpressJS route with a regex to check if a store code exists inside the URL (and more magic) and redirect to the first store-code in config.storeViews.mapStoreUrlsFor.
My src/modules/custom-module/server.ts looks like this:
import appConfig from 'config'
import { serverHooks } from '@vue-storefront/core/server/hooks'
if (appConfig.storeViews.multistore) {
serverHooks.afterApplicationInitialized(({ app }) => {
const blacklist = ['__webpack_hmr']
const storeCodes = appConfig.storeViews.mapStoreUrlsFor
const blacklistStr = blacklist.join('|')
const storeCodesStr = storeCodes.join('|')
const hasStoreCode = new RegExp(
`^((?!\\/(${storeCodesStr})(\\/|$))(?!\\/(${blacklistStr})$))\\/?.*((?<=\\.html)|(?<!\\.[a-zA-Z0-9]*))$`
)
app.get(hasStoreCode, (req, res) => {
const { path } = req
const newUrl = '/' + storeCodes[0] + path
let query = ''
if (Object.values(req.query).length > 0) {
const params = new URLSearchParams(req.query)
query += '?' + params.toString()
}
res.redirect(newUrl + query)
console.log('Redirect to default:', newUrl)
})
})
}
This isn't tested anywhere else but for my environment – you should check yourself if this catches all your use cases.
@cewald great job; can you submit this module (as a separate npm - to the forum.vuestorfront.io modules section) or even to the core (src/modules)?
I solved it by adding a second store, like which inherits from my desired default one.
For example: I'm having a german store config which I wan't to be the default store. So in best case the default store should also be available in
http://localhost/specific/urlandhttp://localhost/de/specific/url– so both is the/destore.My solution would be to use the
extendflag to extend from the default store ore visa versa to achieve this like:{ "defaultStoreCode": "default", "storeViews": { "mapStoreUrlsFor": ["de", "fr", "uk", "it"], "default": { "storeCode": "default", "storeId": 1, "name": "German Store", "url": "/", "appendStoreCode": false, "disabled": false, "elasticsearch": { "host": "/api/catalog", "index": "vue_storefront_catalog_1" }, "tax": { "sourcePriceIncludesTax": false, "defaultCountry": "DE", "defaultRegion": "", "calculateServerSide": true } }, "de": { "extend": "default", "storeCode": "de", "storeId": 1, "appendStoreCode": true, "disabled": false, "elasticsearch": { "host": "/api/catalog", "index": "vue_storefront_catalog_1" } }, "fr": { "extend": "de", "storeCode": "fr", "storeId": 12, "name": "French Store", "url": "/fr", "appendStoreCode": true, "disabled": false, "elasticsearch": { "index": "vue_storefront_catalog_12" }, "tax": { "defaultCountry": "FR" }, "i18n": { "fullCountryName": "France", "fullLanguageName": "French", "defaultLanguage": "FR", "defaultCountry": "FR", "defaultLocale": "fr-FR" } }, ... }, "i18n": { "defaultCountry": "DE", "defaultLanguage": "DE", "availableLocale": ["en-GB","de-DE","fr-FR","it-IT"], "defaultLocale": "de-DE", "currencyCode": "EUR", "currencySign": "€", "currencySignPlacement": "append", "dateFormat": "HH:mm D.M.YYYY", "fullCountryName": "Germany", "fullLanguageName": "German", "bundleAllStoreviewLanguages": true }, ... }In fact extending the configs isn't working totally smooth yet, like
"appendStoreCode": truehas to be on each node, etc. – but it is working for us at the moment and leaves a lot of flexibility without changing the code at the core.
Have you also set up a default store in Magento to make it work? I triet your config but it doesn't work as it should :(