Skip to content

Commit

Permalink
feat(vue-demo): leverage edge cache (#309)
Browse files Browse the repository at this point in the history
* feat(vue-demo): leverage edge cache

* chore: account page

* chore: clear session data

* chore: session test

* chore: lazy images

* chore: client only logged user indicator

* chore: sign in client only

* chore: update cache rules

* test: disable cookies on SSR

* chore: more lazy images

* feat: config for user context in ssr

* chore: changesets

* fix: login on register page
  • Loading branch information
patzick authored Jul 11, 2023
1 parent 8c6ff0a commit 84a7fe6
Show file tree
Hide file tree
Showing 18 changed files with 283 additions and 99 deletions.
5 changes: 5 additions & 0 deletions .changeset/dull-steaks-beam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@shopware-pwa/nuxt3-module": minor
---

Added new config `useUserContextInSSR` - set to true if you want for the server to use session from cookie and prepare view with it. Use carefully with edge caching to avoid sharing user data with edge cache. Default is false, so server will always use new context to prepare rendered view.
5 changes: 5 additions & 0 deletions .changeset/eight-rivers-peel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"vue-demo-store": minor
---

Session data are no longer rendered on server. Improved edge caching to achieve better performence.
6 changes: 6 additions & 0 deletions .changeset/gold-rockets-shave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"vue-demo-store": minor
"@shopware-pwa/cms-base": minor
---

Images are now lazy loaded, saves data on initial page load
1 change: 1 addition & 0 deletions packages/cms-base/components/SwProductCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ const srcPath = computed(() => {
>
<img
ref="imageElement"
loading="lazy"
:src="srcPath"
:alt="getProductName({ product }) || ''"
class="transform transition duration-400 hover:scale-120"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const toggle = () => {
<div v-if="option.media?.url">
<img
loading="lazy"
class="ml-2 h-4 w-4"
:src="option.media.url"
:alt="option.media.translated?.alt || ''"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const srcPath = computed(() => {
>
<img
ref="imageElement"
loading="lazy"
:class="{
'h-full w-full': true,
'absolute inset-0': ['cover', 'stretch'].includes(displayMode),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ function next() {
@click="() => changeCover(i)"
>
<img
loading="lazy"
:src="image.media.url"
class="w-full h-full object-center object-cover"
alt="Product image"
Expand Down
40 changes: 26 additions & 14 deletions packages/nuxt3-module/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ const ShopwarePlugin = {
install(app, options) {
const runtimeConfig = useRuntimeConfig();

const useUserCookieContext =
!!runtimeConfig.public?.shopware?.useUserContextInSSR ||
!options.isServer;

const contextToken = useCookie("sw-context-token", {
maxAge: 60 * 60 * 24 * 365,
sameSite: "Lax",
Expand Down Expand Up @@ -47,26 +51,33 @@ const ShopwarePlugin = {
password:
"<%= options.shopwareApiClient.auth ? options.shopwareApiClient.auth.password : undefined %>",
},
contextToken: contextToken.value || cookieContextToken,
languageId: languageId.value || cookieLanguageId,
contextToken: useUserCookieContext
? contextToken.value || cookieContextToken
: "",
languageId: useUserCookieContext
? languageId.value || cookieLanguageId
: undefined,
});
/**
* Save current contextToken when its change
*/
instance.onConfigChange(({ config }) => {
try {
contextToken.value = config.contextToken;
languageId.value = config.languageId;
Cookies.set("sw-context-token", config.contextToken || "", {
expires: 365, //days
sameSite: "Lax",
path: "/",
});
Cookies.set("sw-language-id", config.languageId || "", {
expires: 365, //days
sameSite: "Lax",
path: "/",
});
// only save cookies on client side render
if (useUserCookieContext) {
contextToken.value = config.contextToken;
languageId.value = config.languageId;
Cookies.set("sw-context-token", config.contextToken || "", {
expires: 365, //days
sameSite: "Lax",
path: "/",
});
Cookies.set("sw-language-id", config.languageId || "", {
expires: 365, //days
sameSite: "Lax",
path: "/",
});
}
} catch (e) {
// Sometimes cookie is set on server after request is send, it can fail silently
}
Expand All @@ -88,5 +99,6 @@ const ShopwarePlugin = {
export default defineNuxtPlugin(async (nuxtApp) => {
nuxtApp.vueApp.use(ShopwarePlugin, {
apiDefaults: getDefaultApiParams(),
isServer: !!nuxtApp.ssrContext,
});
});
7 changes: 7 additions & 0 deletions packages/nuxt3-module/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ export type ShopwareNuxtOptions = {
apiClientConfig?: {
timeout?: number | string;
};
/**
* Use user context in SSR mode. Warning: with wrong edge caching it can cause serving another user's data.
* Use when edge caching is configured properly.
*
* @default false
*/
useUserContextInSSR?: boolean;
};

declare module "@nuxt/schema" {
Expand Down
97 changes: 95 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 10 additions & 6 deletions templates/vue-demo-store/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@ useHead({
});
const { apiInstance } = useShopwareContext();
const { data: sessionContextData } = await useAsyncData(
"sessionContext",
async () => {
return await getSessionContext(apiInstance);
}
);
const sessionContextData = ref();
sessionContextData.value = await getSessionContext(apiInstance);
// If you enable runtimeConfig.shopware.useUserContextInSSR, then you can use this code to share session between server and client.
// const { data: sessionContextData } = await useAsyncData(
// "sessionContext",
// async () => {
// return await getSessionContext(apiInstance);
// }
// );
// read the locale from accept-language header (i.e. en-GB or de-DE)
// and set configuration for price formatting globally
Expand Down
Loading

2 comments on commit 84a7fe6

@vercel
Copy link

@vercel vercel bot commented on 84a7fe6 Jul 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 84a7fe6 Jul 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

frontends-demo – ./templates/vue-demo-store

frontends-demo.vercel.app
frontends-demo-git-main-shopware-frontends.vercel.app
frontends-demo-shopware-frontends.vercel.app

Please sign in to comment.