Skip to content

Commit

Permalink
feat: added support for @vue-storefront/cache module (#482)
Browse files Browse the repository at this point in the history
* chore(theme): added nuxt-image

* feat(theme): added nuxt-img to category page

* feat: added nuxt-img to category pages, added newe configs, and useImage compoosable

* feat(theme): added nuxt-img to products carousel, added image enums

* feat(theme): added nuxt-img for search results

* feat(theme): added nuxt-img to my account wishlist

* feat(theme): changed log to use nuxt-img

* feat(theme): changed empty cart icon to use nuxt-img

* feat(theme): added nuxt-img to instagram feed, updated image names

* feat(theme): changed error image on search results to use nuxt-img

* feat(theme): update store switcher to use nuxt-img instead of SfImage

* feat(theme): added nuxt-img to wishlist sidebar

* feat(theme): added nuxt-img to MobileStoreBanner

* feat(theme): added nuxt-img to grouoped product selector

* feat(theme): added nuxt-img to payment component

* docs: added docs for external images providers

* build(cloud): updated vuestorefront cloud docker file and added new args

* build: updated deploy gh action to add image env vatiables

* docs(configuration): updated docs for image providers

* build: added missed buildargs

* build: fixed dockerfile

* build: fixed typo in docker file

* build: updated config

* test: add unit tests for the useImage composable

* chore(theme): added @vue-storefront-cache module

* chore(theme): added config for @vue-storefront/cache to nuxt.config.js

* feat(theme): added cache tags to home and category page

* chore(theme): added redis-cache module, fixed cache tags for category page

* feat(theme): added cache tags to product page, added body parser server middleware

* build: added config for redis, modified deployment config for tests

* build: removed unnecessary redis_password env variable

* build: fixed redis env variables names

* feat(theme): added cache tags for cms pages

* chore(theme): removed console.logs, added comments to nuxt.config.js

* build: removed redis-cache module from package.json and addet it to dockerfile

* build: updated dockerfile

* build(updzted docker file): updated dovkerfile

* build: added REDIS__ENABLED env variable

* docs: added docs for redis caching

* build: reverted test changes in deploy action

* fix(theme): removed typo from Category template

n

* build: fixed GH deploy action
  • Loading branch information
Frodigo authored Jan 28, 2022
1 parent de3e8ff commit 2525c72
Show file tree
Hide file tree
Showing 14 changed files with 20,633 additions and 26,967 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/deploy-vue-storefront-cloud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
password: ${{ secrets.CLOUD_PASSWORD }}
dockerfile: .vuestorefrontcloud/docker/Dockerfile
buildoptions: --compress
buildargs: NPM_EMAIL,NPM_PASS,NPM_USER,NPM_REGISTRY,STORE_URL,MAGENTO_GRAPHQL,MAGENTO_EXTERNAL_CHECKOUT,MAGENTO_EXTERNAL_CHECKOUT_URL,MAGENTO_EXTERNAL_CHECKOUT_SYNC_PATH,IMAGE_PROVIDER,IMAGE_PROVIDER_BASE_URL,SENTRY_DSN
buildargs: NPM_EMAIL,NPM_PASS,NPM_USER,NPM_REGISTRY,STORE_URL,MAGENTO_GRAPHQL,MAGENTO_EXTERNAL_CHECKOUT,MAGENTO_EXTERNAL_CHECKOUT_URL,MAGENTO_EXTERNAL_CHECKOUT_SYNC_PATH,IMAGE_PROVIDER,IMAGE_PROVIDER_BASE_URL,REDIS__HOST,REDIS__PORT,REDIS__CACHE_INVALIDATE_KEY,REDIS__CACHE_INVALIDATE_URL,REDIS__KEY_PREFIX,REDIS__ENABLED,SENTRY_DSN
env:
NPM_EMAIL: ${{ secrets.NPM_EMAIL }}
NPM_PASS: ${{ secrets.CLOUD_PASSWORD }}
Expand All @@ -38,6 +38,12 @@ jobs:
MAGENTO_EXTERNAL_CHECKOUT_SYNC_PATH: ${{ secrets.MAGENTO_EXTERNAL_CHECKOUT_SYNC_PATH }}
IMAGE_PROVIDER: ${{ secrets.IMAGE_PROVIDER }}
IMAGE_PROVIDER_BASE_URL: ${{ secrets.IMAGE_PROVIDER_BASE_URL }}
REDIS__HOST: ${{ secrets.REDIS__HOST }}
REDIS__PORT: ${{ secrets.REDIS__PORT }}
REDIS__KEY_PREFIX: ${{ secrets.REDIS__KEY_PREFIX }}
REDIS__CACHE_INVALIDATE_KEY: ${{ secrets.REDIS__CACHE_INVALIDATE_KEY }}
REDIS__CACHE_INVALIDATE_URL: ${{ secrets.REDIS__CACHE_INVALIDATE_URL }}
REDIS__ENABLED: ${{ secrets.REDIS__ENABLED }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
deploy:
runs-on: ubuntu-latest
Expand Down
20 changes: 19 additions & 1 deletion .vuestorefrontcloud/docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ ARG STORE_URL
ARG MAGENTO_BASE_URL
ARG IMAGE_PROVIDER
ARG IMAGE_PROVIDER_BASE_URL
ARG REDIS__HOST
ARG REDIS__PORT
ARG REDIS__CACHE_INVALIDATE_KEY
ARG REDIS__CACHE_INVALIDATE_URL
ARG REDIS__CACHE_INVALIDATE_URL
ARG REDIS__KEY_PREFIX
ARG REDIS__ENABLED
ARG SENTRY_DSN

ENV MAGENTO_GRAPHQL=${MAGENTO_GRAPHQL}
Expand All @@ -27,6 +34,13 @@ ENV NUXT_APP_PORT=3000
ENV MAGENTO_BASE_URL=https://magento2-instance.vuestorefront.io/
ENV IMAGE_PROVIDER=${IMAGE_PROVIDER}
ENV IMAGE_PROVIDER_BASE_URL=${IMAGE_PROVIDER_BASE_URL}
ENV REDIS__HOST=${REDIS__HOST}
ENV REDIS__PORT=${REDIS__PORT}
ENV REDIS__CACHE_INVALIDATE_KEY=${REDIS__CACHE_INVALIDATE_KEY}
ENV REDIS__CACHE_INVALIDATE_URL=${REDIS__CACHE_INVALIDATE_URL}
ENV REDIS__CACHE_INVALIDATE_URL=${REDIS__CACHE_INVALIDATE_URL}
ENV REDIS__KEY_PREFIX=${REDIS__KEY_PREFIX}
ENV REDIS__ENABLED=${REDIS__ENABLED}
ENV SENTRY_DSN=${SENTRY_DSN}


Expand All @@ -37,7 +51,11 @@ WORKDIR /var/www

COPY . .

RUN yarn install && yarn build && yarn cache clean --all
RUN yarn install

RUN npx [email protected] workspace @vue-storefront/magento-theme add @vsf-enterprise/redis-cache

RUN yarn build && yarn cache clean --all

COPY .vuestorefrontcloud/docker/vue-storefront.sh /usr/local/bin/

Expand Down
13 changes: 11 additions & 2 deletions docs/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ module.exports = {
{ text: 'Core Documentation', link: 'https://docs.vuestorefront.io/v2/' },
{ text: 'Demo', link: 'https://demo-magento2.europe-west1.gcp.storefrontcloud.io/' },
{ text: 'GitHub', link: 'https://github.com/vuestorefront/magento2'},
{ text: 'Roadmap', link: 'https://github.com/vuestorefront/magento2/projects/5'}
{ text: 'Roadmap', link: 'https://docs.vuestorefront.io/magento/guide/roadmap.html'},
{ text: 'Environments', link: 'https://docs.vuestorefront.io/magento/guide/environments.html'}
],
sidebar: [
{
Expand All @@ -66,13 +67,21 @@ module.exports = {
collapsable: false,
children: [
['/guide/creating-a-store', 'Creating a Store'],
['/guide/graphql-get', 'Use GET for GraphQL Queries'],
['/guide/configuration', 'Configuration'],
['/guide/override-queries', 'Override queries'],
['/guide/testing', 'Testing'],
['/guide/recaptcha', 'ReCaptcha'],
['/guide/testing', 'Testing']
]
},
{
title: 'Performance',
collapsable: false,
children: [
['/guide/graphql-get', 'Varnish & GET for GraphQL Queries'],
['/guide/ssr', 'Server Side Rendering Cache'],
]
},
{
title: 'Composables',
children: [
Expand Down
91 changes: 91 additions & 0 deletions docs/guide/ssr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Server-Side Rendering Cache

## Introduction

VueStorefront 2 - Magento 2 integrations use @vue-storefront/cache module that adds posibility to cache some server-side
rendered pages.

### What is cached
The cached pages are:

* Home page with the `Vhome` tag.
* All CMS pages with the `V${page.identifier}` tag
* Category page with the `Vcategory` tag and tags for products: `P${product.uid}` as well as categories `C${category.slug}`
* Product page with the `Vproduct-${route.value.params.id}` tag and tags for the main product `P${product.uid}` as well as categories `C${cat.id}`

## Invalidating tags

To invalidate a tag and remove pages associated with that tag, use the [Invalidation endpoint](https://docs.vuestorefront.io/v2/performance/ssr-cache.html#invalidating-tags).

Go to the route configured in the `.env` file under the `REDIS__CACHE_INVALIDATE_KEY` key with two query parameters:
* `key` — string matching the `REDIS__CACHE_INVALIDATE_KEY` key in the `.env` file.
* `tags` — a comma-separated list of tags for invalidation.

Assuming that you are running the application locally, the `REDIS__CACHE_INVALIDATE_URL` key is equal to `/cache-invalidate,` and the `REDIS__CACHE_INVALIDATE_KEY` key is equal to `secret_key`, and you want to invalidate the `Vhome` tag, the full URL will look like this:

## How to cache other pages

We added caching only to the most visited pages. However, you can cache other pages as well, including custom ones. You can find detailed instructions on how to use cache on the [SSR Cache](https://docs.vuestorefront.io/v2/performance/ssr-cache.html) and [Redis cache](https://docs.vuestorefront.io/v2/integrations/redis-cache.html) pages.

:::tip
You don't need to add any additional packages to cache more pages — just add or modify tags in components.
:::

## Cache drivers

@vue-storefront/cache module is open source and provided Out Of The Box by Magento 2 integration.
To set up caching in your store, you must install and configure a cache driver.
You can use our enterprise `@vsf-enterprise/redis-cache` module, or build your cache driver.

### Redis cache (enterprise)
Once you have access to the [Vue Storefront npm registry](https://docs.vuestorefront.io/v2/general/enterprise.htm),
you can install the Redis cache driver by running this command in a console:

``yarn add @vsf-enterprise/redis-cache``


#### redis cache configuration

Once you have the Redis driver installed, you need to add the Redis configuration to your project's `.env` file.

```
.env
REDIS__HOST=127.0.0.1
REDIS__PORT=6379
REDIS_PASSWORD=
REDIS__KEY_PREFIX=
REDIS__CACHE_INVALIDATE_URL=/cache-invalidate
REDIS__ENABLED=false
```

Then you have to update `nuxt.config.js file` and add this to the `modules` object:

```javascript
['@vue-storefront/cache/nuxt', {
enabled: process.env.REDIS__ENABLED,
invalidation: {
endpoint: process.env.REDIS__CACHE_INVALIDATE_URL,
key: process.env.REDIS__CACHE_INVALIDATE_KEY,
handlers: [
'@vue-storefront/cache/defaultHandler',
],
},
driver: [
'@vsf-enterprise/redis-cache',
{
// docs: https://github.com/luin/ioredis/blob/master/API.md#new-redisport-host-options
redis: {
keyPrefix: process.env.REDIS__KEY_PREFIX,
host: process.env.REDIS__HOST,
port: process.env.REDIS__PORT,
},
},
],
}],
```

## Useful links

- https://docs.vuestorefront.io/v2/performance/ssr-cache.html
- https://docs.vuestorefront.io/v2/integrations/redis-cache.html
- https://docs.vuestorefront.io/v2/integrate/cache-driver.html
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,5 @@
"node": ">=16.x.x",
"yarn": "1.x.x||>=3.x.x"
},
"packageManager": "yarn@3.1.1"
"packageManager": "yarn@1.22.15"
}
9 changes: 9 additions & 0 deletions packages/theme/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,12 @@ MAGENTO_EXTERNAL_CHECKOUT_SYNC_PATH=/vue/cart/sync
MAGENTO_BASE_URL={YOUR_SITE_FRONT_URL}
IMAGE_PROVIDER={YOUR_IMAGE_PROVIDER}
IMAGE_PROVIDER_BASE_URL={YOUR_IMAGE_PROVIDER_BASE_URL}
MAGENTO_BASE_URL={YOUR_SITE_FRONT_URL}
IMAGE_PROVIDER={YOUR_IMAGE_PROVIDER}
IMAGE_PROVIDER_BASE_URL={YOUR_IMAGE_PROVIDER_BASE_URL}
REDIS__HOST=127.0.0.1
REDIS__PORT=6379
REDIS_PASSWORD=
REDIS__KEY_PREFIX=
REDIS__CACHE_INVALIDATE_URL=/cache-invalidate
REDIS__ENABLED=false
26 changes: 26 additions & 0 deletions packages/theme/nuxt.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,29 @@ export default {
'@nuxt/image',
'@nuxtjs/sentry',
// '@nuxtjs/recaptcha',
['@vue-storefront/cache/nuxt', {
enabled: process.env.REDIS__ENABLED,
invalidation: {
endpoint: process.env.REDIS__CACHE_INVALIDATE_URL,
key: process.env.REDIS__CACHE_INVALIDATE_KEY,
handlers: [
'@vue-storefront/cache/defaultHandler',
],
},
driver: [
// project only start:
'@vsf-enterprise/redis-cache',
{
// docs: https://github.com/luin/ioredis/blob/master/API.md#new-redisport-host-options
redis: {
keyPrefix: process.env.REDIS__KEY_PREFIX,
host: process.env.REDIS__HOST,
port: process.env.REDIS__PORT,
},
},
// project only end
],
}],
],
recaptcha: {
hideBadge: config.get('recaptchaHideBadge'), // Hide badge element (v3 & v2 via size=invisible)
Expand Down Expand Up @@ -252,6 +275,9 @@ export default {
'~/plugins/i18n',
'~/plugins/fcPlugin',
],
serverMiddleware: [
'~/serverMiddleware/body-parser.js',
],
router: {
extendRoutes(routes) {
getRoutes(`${__dirname}/_theme`)
Expand Down
1 change: 1 addition & 0 deletions packages/theme/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@nuxtjs/style-resources": "^1.2.1",
"@sentry/tracing": "^6.17.2",
"@storefront-ui/vue": "^0.11.5",
"@vue-storefront/cache": "^2.5.4",
"@vue-storefront/core": "~2.5.4",
"@vue-storefront/magento": "1.0.0-rc.5.3",
"@vue-storefront/middleware": "~2.5.4",
Expand Down
15 changes: 15 additions & 0 deletions packages/theme/pages/Category.vue
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ import {
useWishlist,
} from '@vue-storefront/magento';
import { onSSR, useVSFContext } from '@vue-storefront/core';
import { useCache, CacheTagPrefix } from '@vue-storefront/cache';
import { useUrlResolver } from '~/composables/useUrlResolver.ts';
import { useUiHelpers, useUiState, useImage } from '~/composables';
import cacheControl from '~/helpers/cacheControl';
Expand Down Expand Up @@ -466,6 +467,7 @@ export default defineComponent({
}),
transition: 'fade',
setup() {
const { addTags } = useCache();
const uiHelpers = useUiHelpers();
const uiState = useUiState();
const {
Expand Down Expand Up @@ -641,6 +643,19 @@ export default defineComponent({
await searchCategoryProduct();
isProductsLoading.value = false;
}
const tags = [{ prefix: CacheTagPrefix.View, value: 'category' }];
// eslint-disable-next-line no-underscore-dangle
const productTags = products.value.map((product) => {
return { prefix: CacheTagPrefix.Product, value: product.uid };
});
const categoriesTags = categoryTree.value.items.map((category) => {
return { prefix: CacheTagPrefix.Category, value: category.slug };
});
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
addTags(tags.concat(productTags, categoriesTags));
});
const { getMagentoImage, imageSizes } = useImage();
Expand Down
7 changes: 7 additions & 0 deletions packages/theme/pages/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ import {
} from '@nuxtjs/composition-api';
import { onSSR } from '@vue-storefront/core';
import LazyHydrate from 'vue-lazy-hydration';
import { useCache, CacheTagPrefix } from '@vue-storefront/cache';
import MobileStoreBanner from '~/components/MobileStoreBanner.vue';
import InstagramFeed from '~/components/InstagramFeed.vue';
import ProductsCarousel from '~/components/ProductsCarousel.vue';
Expand All @@ -95,6 +96,8 @@ export default defineComponent({
},
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
setup() {
const { addTags } = useCache();
const {
products: newProductsResult,
search: newProductsSearch,
Expand Down Expand Up @@ -215,6 +218,10 @@ export default defineComponent({
position: 'ASC',
},
});
addTags([
{ prefix: CacheTagPrefix.View, value: 'home' }
]);
});
return {
Expand Down
4 changes: 4 additions & 0 deletions packages/theme/pages/Page.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { useContent } from '@vue-storefront/magento';
import { onSSR } from '@vue-storefront/core';
import { defineComponent, useContext, useRoute } from '@nuxtjs/composition-api';
import HTMLContent from '~/components/HTMLContent';
import { useCache, CacheTagPrefix } from '@vue-storefront/cache';
export default defineComponent({
components: {
Expand All @@ -36,6 +37,7 @@ export default defineComponent({
},
},
setup(props) {
const { addTags } = useCache();
const {
page,
error,
Expand All @@ -49,6 +51,8 @@ export default defineComponent({
onSSR(async () => {
await loadContent({ identifier: params.slug || props.identifier });
if (error?.value?.content) nuxtError({ statusCode: 404 });
addTags([{ prefix: CacheTagPrefix.View, value: page.value.identifier }]);
});
return {
page,
Expand Down
10 changes: 10 additions & 0 deletions packages/theme/pages/Product.vue
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ import UpsellProducts from '~/components/UpsellProducts';
import RelatedProducts from '~/components/RelatedProducts';
import HTMLContent from '~/components/HTMLContent';
import AddToWishlist from '~/components/AddToWishlist';
import { useCache, CacheTagPrefix } from '@vue-storefront/cache';
export default defineComponent({
name: 'ProductPage',
Expand Down Expand Up @@ -331,6 +332,7 @@ export default defineComponent({
}),
transition: 'fade',
setup() {
const { addTags } = useCache();
const qty = ref(1);
const {
product,
Expand Down Expand Up @@ -476,6 +478,14 @@ export default defineComponent({
if (product?.value?.length === 0) nuxtError({ statusCode: 404 });
await searchReviews(baseSearchQuery);
const tags = [{ prefix: CacheTagPrefix.View, value: `product-${route.value.params.id}` }];
const productTags = { prefix: CacheTagPrefix.Product, value: product.value.uid };
const categoriesTags = categories.value.map((catId) => {
return { prefix: CacheTagPrefix.Category, value: catId };
});
addTags(tags.concat(productTags, categoriesTags));
});
return {
Expand Down
5 changes: 5 additions & 0 deletions packages/theme/serverMiddleware/body-parser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const bodyParser = require('body-parser');
const app = require('express')();

app.use(bodyParser.json());
module.exports = app;
Loading

0 comments on commit 2525c72

Please sign in to comment.