Skip to content

Commit cf78686

Browse files
fix(os-203): fixed adding custom router.base property breaks api calls (vuestorefront#6526) (vuestorefront#6592)
Co-authored-by: Piotr Grzywa <pgrzywa@vuestorefront.io> Co-authored-by: Piotr Grzywa <pgrzywa@vuestorefront.io>
1 parent eda93ff commit cf78686

File tree

21 files changed

+175
-64
lines changed

21 files changed

+175
-64
lines changed

packages/boilerplate/theme/nuxt.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export default {
1919
{
2020
rel: 'icon',
2121
type: 'image/x-icon',
22-
href: '/favicon.ico'
22+
href: './favicon.ico'
2323
},
2424
{
2525
rel: 'preconnect',
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { useRouter } from '@nuxtjs/composition-api';
2+
3+
/**
4+
* Adds prefix with base path configured in router.base to provided url
5+
* @param {string} path - url to which base path will be added
6+
* @returns Relative path prefixed with router.base or not modified absolute path (it needs start from http or https)
7+
*/
8+
function addBasePath (path: string): string {
9+
const pattern = /^((http|https):\/\/)/;
10+
11+
if (pattern.test(path)) {
12+
return path;
13+
}
14+
15+
const basePath = (useRouter().options.base).slice(0, -1);
16+
return `${basePath}${path}`;
17+
}
18+
19+
export {
20+
addBasePath
21+
};

packages/core/core/src/utils/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { onSSR, vsfRef, configureSSR } from './ssr';
44
import { sharedRef } from './shared';
55
import wrap from './wrap';
66
import { Logger, registerLogger } from './logger';
7+
import { addBasePath } from './helpers';
78
import mask from './logger/mask';
89
import { useVSFContext, configureContext, generateContext } from './context';
910
import { integrationPlugin } from './nuxt';
@@ -24,5 +25,6 @@ export {
2425
configureFactoryParams,
2526
generateContext,
2627
integrationPlugin,
27-
i18nRedirectsUtil
28+
i18nRedirectsUtil,
29+
addBasePath
2830
};

packages/core/core/src/utils/nuxt/_proxyUtils.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ interface CreateProxiedApiParams {
99
tag: string;
1010
}
1111

12-
export const getBaseUrl = (req: IncomingMessage) => {
13-
if (!req) return '/api/';
12+
export const getBaseUrl = (req: IncomingMessage, basePath: string | undefined = '/'): string => {
13+
if (!req) return `${basePath}api/`;
1414
const { headers } = req;
1515
const isHttps = require('is-https')(req);
1616
const scheme = isHttps ? 'https' : 'http';
1717
const host = headers['x-forwarded-host'] || headers.host;
1818

19-
return `${scheme}://${host}/api/`;
19+
return `${scheme}://${host}${basePath}api/`;
2020
};
2121

2222
export const createProxiedApi = ({ givenApi, client, tag }: CreateProxiedApiParams) => new Proxy(givenApi, {
@@ -39,7 +39,7 @@ export const getIntegrationConfig = (context: NuxtContext, configuration: any) =
3939
const cookie = getCookies(context);
4040
const initialConfig = merge({
4141
axios: {
42-
baseURL: getBaseUrl(context?.req),
42+
baseURL: getBaseUrl(context?.req, context?.base),
4343
headers: {
4444
...(cookie ? { cookie } : {})
4545
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module.exports = {
2+
description: 'Fixed adding custom router.base property breaks api calls',
3+
link: 'https://github.com/vuestorefront/vue-storefront/issues/6505',
4+
isBreaking: false,
5+
breakingChanges: [],
6+
author: 'Piotr Grzywa',
7+
linkToGitHubAccount: 'https://github.com/PiotrGrzywa'
8+
};

packages/core/docs/getting-started/theme.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,45 @@ These two components come from the `vue-lazy-hydration` library and are wrappers
3333

3434
If you encounter one of these components, you should refer to the direct **child** component.
3535

36+
### Router base property
37+
38+
There is an option to set base URL for your store.
39+
40+
This can be useful if you need to serve your store as a different context root, from within a bigger Web site.
41+
42+
Add following configuration to `nuxt.config.js`
43+
```javascript
44+
// nuxt.config.js
45+
46+
export default {
47+
router: {
48+
base: "/myShop/"
49+
}
50+
};
51+
```
52+
53+
:::warning Be careful
54+
When using base router property you need to wrap all assets relative links in addBasePath(), this will automatically add base path to them and prevent redirects. (example below)
55+
:::
56+
57+
58+
59+
```javascript
60+
//use addBasePath on relative url
61+
<SfImage :src="addBasePath(`/homepage/imageA.webp`)" />
62+
<SfBanner :image="addBasePath('/homepage/bannerA.png')" />
63+
64+
//In theme file import addBasePath from vue-storefront core
65+
import { addBasePath } from '@vue-storefront/core';
66+
67+
setup() {
68+
return {
69+
// if you want to use it in template you need to exprt it
70+
addBasePath
71+
}
72+
}
73+
```
74+
3675
## Updating styles
3776

3877
There are few ways of updating the default styles. Below we describe the most optimal ways for the most common cases.

packages/core/nuxt-theme-module/theme/components/AppFooter.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,15 @@
5050
</SfFooterColumn>
5151
<SfFooterColumn title="Social">
5252
<div class="footer__socials">
53-
<SfImage class="footer__social-image" v-for="item in social" :key="item" :src="'/icons/'+item+'.svg'" :alt="item" width="32" height="32" />
53+
<SfImage class="footer__social-image" v-for="item in social" :key="item" :src="addBasePath('/icons/'+item+'.svg')" :alt="item" width="32" height="32" />
5454
</div>
5555
</SfFooterColumn>
5656
</SfFooter>
5757
</template>
5858

5959
<script>
6060
import { SfFooter, SfList, SfImage, SfMenuItem } from '@storefront-ui/vue';
61+
import { addBasePath } from '@vue-storefront/core';
6162
6263
export default {
6364
components: {
@@ -66,6 +67,11 @@ export default {
6667
SfImage,
6768
SfMenuItem
6869
},
70+
setup() {
71+
return {
72+
addBasePath
73+
};
74+
},
6975
data() {
7076
return {
7177
aboutUs: ['Who we are', 'Quality in the details', 'Customer Reviews'],

packages/core/nuxt-theme-module/theme/components/AppHeader.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<!-- TODO: add mobile view buttons after SFUI team PR -->
99
<template #logo>
1010
<nuxt-link :to="localePath({ name: 'home' })" class="sf-header__logo">
11-
<SfImage src="/icons/logo.svg" alt="Vue Storefront Next" class="sf-header__logo-image"/>
11+
<SfImage :src="addBasePath('/icons/logo.svg')" alt="Vue Storefront Next" class="sf-header__logo-image"/>
1212
</nuxt-link>
1313
</template>
1414
<template #navigation>
@@ -119,6 +119,7 @@ import {
119119
} from '@storefront-ui/vue/src/utilities/mobile-observer.js';
120120
import debounce from 'lodash.debounce';
121121
import mockedSearchProducts from '../mockedSearchProducts.json';
122+
import { addBasePath } from '@vue-storefront/core';
122123
123124
export default {
124125
components: {
@@ -222,7 +223,8 @@ export default {
222223
searchBarRef,
223224
isMobile,
224225
isMobileMenuOpen,
225-
removeSearchResults
226+
removeSearchResults,
227+
addBasePath
226228
};
227229
}
228230
};

packages/core/nuxt-theme-module/theme/components/CartSidebar.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
v-for="product in products"
2424
v-e2e="'collected-product'"
2525
:key="cartGetters.getItemSku(product)"
26-
:image="cartGetters.getItemImage(product)"
26+
:image="addBasePath(cartGetters.getItemImage(product))"
2727
:title="cartGetters.getItemName(product)"
2828
:regular-price="$n(cartGetters.getItemPrice(product).regular, 'currency')"
2929
:special-price="cartGetters.getItemPrice(product).special && $n(cartGetters.getItemPrice(product).special, 'currency')"
@@ -62,7 +62,7 @@
6262
<SfImage
6363
alt="Empty bag"
6464
class="empty-cart__image"
65-
src="/icons/empty-cart.svg"
65+
:src="addBasePath('/icons/empty-cart.svg')"
6666
/>
6767
<SfHeading
6868
title="Your cart is empty"
@@ -125,6 +125,7 @@ import { computed } from '@nuxtjs/composition-api';
125125
import { useCart, cartGetters } from '<%= options.generate.replace.composables %>';
126126
import { useUiState } from '~/composables';
127127
import debounce from 'lodash.debounce';
128+
import { addBasePath } from '@vue-storefront/core';
128129
129130
export default {
130131
name: 'Cart',
@@ -151,6 +152,7 @@ export default {
151152
}, 500);
152153
153154
return {
155+
addBasePath,
154156
updateQuantity,
155157
loading,
156158
products,

packages/core/nuxt-theme-module/theme/components/InstagramFeed.vue

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,29 @@
33
<div class="grid grid-images">
44
<div class="grid__row">
55
<div class="grid__col">
6-
<SfImage v-if="isMobile" src="/homepage/imageAm.webp" alt="katherina_trn" :width="160" :height="160">katherina_trn</SfImage>
7-
<SfImage v-else src="/homepage/imageAd.webp" alt="katherina_trn" :width="470" :height="470">katherina_trn</SfImage>
6+
<SfImage v-if="isMobile" :src="addBasePath('/homepage/imageAm.webp')" alt="katherina_trn" :width="160" :height="160">katherina_trn</SfImage>
7+
<SfImage v-else :src="addBasePath('/homepage/imageAd.webp')" alt="katherina_trn" :width="470" :height="470">katherina_trn</SfImage>
88
</div>
99
<div class="grid__col small">
10-
<SfImage v-if="isMobile" src="/homepage/imageBm.webp" alt="katherina_trn" :width="160" :height="160">katherina_trn</SfImage>
11-
<SfImage v-else src="/homepage/imageCd.webp" alt="katherina_trn" :width="470" :height="160">katherina_trn</SfImage>
10+
<SfImage v-if="isMobile" :src="addBasePath('/homepage/imageBm.webp')" alt="katherina_trn" :width="160" :height="160">katherina_trn</SfImage>
11+
<SfImage v-else :src="addBasePath('/homepage/imageCd.webp')" alt="katherina_trn" :width="470" :height="160">katherina_trn</SfImage>
1212
</div>
1313
</div>
1414
<div class="grid__row">
1515
<div class="grid__col small">
16-
<SfImage v-if="isMobile" src="/homepage/imageCm.webp" alt="katherina_trn" :width="160" :height="160">katherina_trn</SfImage>
17-
<SfImage v-else src="/homepage/imageBd.webp" alt="katherina_trn" :width="470" :height="160">katherina_trn</SfImage>
16+
<SfImage v-if="isMobile" :src="addBasePath('/homepage/imageCm.webp')" alt="katherina_trn" :width="160" :height="160">katherina_trn</SfImage>
17+
<SfImage v-else :src="addBasePath('/homepage/imageBd.webp')" alt="katherina_trn" :width="470" :height="160">katherina_trn</SfImage>
1818
</div>
1919
<div class="grid__col">
20-
<SfImage v-if="isMobile" src="/homepage/imageDm.webp" alt="katherina_trn" :width="160" :height="160">katherina_trn</SfImage>
21-
<SfImage v-else src="/homepage/imageDd.webp" alt="katherina_trn" :width="470" :height="470">katherina_trn</SfImage>
20+
<SfImage v-if="isMobile" :src="addBasePath('/homepage/imageDm.webp')" alt="katherina_trn" :width="160" :height="160">katherina_trn</SfImage>
21+
<SfImage v-else :src="addBasePath('/homepage/imageDd.webp')" alt="katherina_trn" :width="470" :height="470">katherina_trn</SfImage>
2222
</div>
2323
</div>
2424
</div>
2525
</SfSection>
2626
</template>
2727
<script>
28+
import { addBasePath } from '@vue-storefront/core';
2829
import {
2930
SfSection,
3031
SfImage
@@ -39,6 +40,11 @@ export default {
3940
SfSection,
4041
SfImage
4142
},
43+
setup() {
44+
return {
45+
addBasePath
46+
};
47+
},
4248
computed: {
4349
...mapMobileObserver()
4450
},

0 commit comments

Comments
 (0)