Custom Vue.js project
Follow these steps to integrate Shopware Frontends into an existing, custom Vue.js project
- Install the required dependencies
- Prepare a Vue plugin for better encapsulation
- Configure the API client and create application instance
- Store and handle client state
Creating Vue project
INFO
You can skip this part if you have an existing project.
pnpm create vue@latestMore information about creating a new Vue project can be found here
Install dependencies
First of all, install the required npm dependencies:
pnpm add @shopware/composables @shopware/api-clientAdditionally, to keep the current session context even after page reloads, we are going to install a cookie helper to set and get value of context token in our plugin:
pnpm add js-cookieFor CMS components, you can add a package that contains ready-to-use components. You can read more about CMS pages here:
# ✨ Auto-detect
npx nypm install -D @shopware/cms-base-layer
# npm
npm install -D @shopware/cms-base-layer
# yarn
yarn add -D @shopware/cms-base-layer
# pnpm
pnpm add -D @shopware/cms-base-layer
# bun
bun install -D @shopware/cms-base-layer
# deno
deno install --dev npm:@shopware/cms-base-layerConfigure API client
Code example
Find a full example of the Vue.js plugin here.
Now, let's configure the API client and business logic together.
INFO
The business logic is written to be Vue 3 compatible. Under the hood, it utilizes the composition API, especially the provide/inject feature for sharing state.
In order to configure the business logic and API client together with your Vue 3 application, it's required to create a Shopware instance provided by a factory method within the @shopware/composables package. Everything will be encapsulated in a plugin and installed later on.
Vue plugins
This section requires having knowledge about the concept of Vue 3 plugins.
Import necessary methods from @shopware/api-client, @shopware/composables and js-cookie packages:
import { createAPIClient } from "@shopware/api-client";
import { createShopwareContext } from "@shopware/composables";
import Cookies from "js-cookie";
// ./plugins/vue-shopware-frontends.ts file
import type { App } from "vue";
import { ref } from "vue";
interface ShopwareFrontendsOptions {
accessToken: string;
endpoint: string;
}
export default {
install: (app: App, options: ShopwareFrontendsOptions) => {
// Configure the API client and Shopware context here.
},
};We prepare some types to be used during the registration of the plugin to pass basic credentials for your Shopware 6 instance.
export type ShopwareFrontendsOptions = {
endpoint: string;
accessToken: string;
shopwareApiClient?: {
timeout: number;
};
enableDevtools?: boolean;
};Now, once the plugin is created, we need to create an API client instance and the Shopware instance for Vue application.
The install method is a good place to do that:
import { createAPIClient } from "@shopware/api-client";
import type { operations } from "@shopware/api-client/store-api-types";
import Cookies from "js-cookie";
import { ref } from "vue";
import type { ShopwareFrontendsOptions } from "./configure-api-client-2";
const options: ShopwareFrontendsOptions = {
endpoint: "https://demo-frontends.swstage.store/store-api",
accessToken: "SWSCBHFSNTVMAWNZDNFKSHLAYW",
shopwareApiClient: {
timeout: 5000,
},
};
const cookieContextToken = Cookies.get("sw-context-token");
const cookieLanguageId = Cookies.get("sw-language-id");
const contextToken = ref(cookieContextToken);
const languageId = ref(cookieLanguageId);
const apiClient = createAPIClient<operations>({
baseURL: options.endpoint,
accessToken: options.accessToken,
fetchOptions: {
timeout: options.shopwareApiClient?.timeout || 5000,
},
contextToken: contextToken.value,
defaultHeaders: {
"sw-language-id": languageId.value,
},
});
export { apiClient, contextToken, languageId };Handle client state
Code example
Complete code example can be found HERE you can find a full example of the plugin
Now, we need to ensure that the context token, which identifies a user session, is properly stored and updated. The context token may change after operations like login or logout.
Then, we can take advantage of the onDefaultHeaderChanged hook. It executes when the API client detects a changed default header value coming from the API (as a header parameter or in the response body). In that case, the new context token should be saved in the cookie to keep the correct session:
import { createAPIClient } from "@shopware/api-client";
import type { operations } from "@shopware/api-client/store-api-types";
import Cookies from "js-cookie";
import { ref } from "vue";
const contextToken = ref(Cookies.get("sw-context-token"));
const languageId = ref(Cookies.get("sw-language-id"));
const apiClient = createAPIClient<operations>({
baseURL: "https://demo-frontends.swstage.store/store-api",
accessToken: "SWSCBHFSNTVMAWNZDNFKSHLAYW",
contextToken: contextToken.value,
defaultHeaders: {
"sw-language-id": languageId.value,
},
});
/**
* Save current contextToken when it changes
*/
apiClient.hook("onDefaultHeaderChanged", (headerName, value) => {
try {
const headerValue = typeof value === "string" ? value : "";
if (headerName === "sw-context-token") {
Cookies.set("sw-context-token", headerValue, {
expires: 365,
sameSite: "Lax",
path: "/",
});
contextToken.value = headerValue;
}
if (headerName === "sw-language-id") {
Cookies.set("sw-language-id", headerValue, {
expires: 365,
sameSite: "Lax",
path: "/",
});
languageId.value = headerValue;
}
} catch (error) {
void error;
// Sometimes cookie is set on server after request is send, it can fail silently
}
});Another step is to create a Shopware instance that combines API Client and the business logic in composables to be used in entire Vue application:
import { createShopwareContext } from "@shopware/composables";
import { createApp } from "vue";
const app = createApp({});
const options = {
enableDevtools: false,
};
const shopwareContext = createShopwareContext(app, {
enableDevtools: !!options.enableDevtools, // decide if devtools should be enabled
});
export { shopwareContext };And the last step is to provide the shopwareContext:
import { createAPIClient } from "@shopware/api-client";
import type { operations } from "@shopware/api-client/store-api-types";
import { createShopwareContext } from "@shopware/composables";
import { createApp, ref } from "vue";
const app = createApp({});
const apiClient = createAPIClient<operations>({});
const shopwareContext = createShopwareContext(app, {});
app.provide("apiClient", apiClient);
app.provide("shopware", shopwareContext);
// thanks to this, `shopwareContext` can be injected in a component and other Vue-instance-aware places (like composables).
app.provide("swSessionContext", ref());Register the plugin
// main.ts
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
// import previously implemented module
import ShopwareFrontends from "./plugins/vue-shopware-frontends";
const app = createApp(App);
app.use(ShopwareFrontends, {
// pass options described under ShopwareFrontendsOptions type in the previous section
endpoint: "https://demo-frontends.swstage.store",
accessToken: "SWSCBHFSNTVMAWNZDNFKSHLAYW",
apiDefaults: {},
});
app.mount("#app");Plugin code
import { createAPIClient } from "@shopware/api-client";
import type { operations } from "@shopware/api-client/store-api-types";
import { createShopwareContext } from "@shopware/composables";
import Cookies from "js-cookie";
// ./plugins/vue-shopware-frontends.ts file
import { ref } from "vue";
import type { App } from "vue";
// Types to be used during the registration of the plugin to pass basic credentials for your Shopware 6 instance.
export type ShopwareFrontendsOptions = {
endpoint: string;
accessToken: string;
shopwareApiClient?: {
timeout: number;
};
enableDevtools?: boolean;
};
export default {
install: (app: App, options: ShopwareFrontendsOptions) => {
const cookieContextToken = Cookies.get("sw-context-token");
const cookieLanguageId = Cookies.get("sw-language-id");
const contextToken = ref(cookieContextToken);
const languageId = ref(cookieLanguageId);
const apiClient = createAPIClient<operations>({
baseURL: options.endpoint,
accessToken: options.accessToken,
contextToken: contextToken.value,
fetchOptions: {
timeout: options.shopwareApiClient?.timeout || 5000,
},
defaultHeaders: {
"sw-language-id": languageId.value,
},
});
const shopwareContext = createShopwareContext(app, {
enableDevtools: !!options.enableDevtools,
});
app.provide("apiClient", apiClient);
app.provide("shopware", shopwareContext);
app.provide("swSessionContext", ref());
},
};Shopware Endpoint on the SSR mode
It may happen that for SSR and CSR, you need two different shopware endpoints. One of the most common situations is when you are using an internal network for communication between apps.
Server URL to the backend: http://shopware (not exposed)
Client URL to the backend https://demo-frontends.shopware.store (exposed)If you are using the Nuxt plugin, you can set private and public envs:
NUXT_SHOPWARE_ENDPOINT=http://shopware
NUXT_PUBLIC_SHOPWARE_ENDPOINT=https://demo-frontends.shopware.storeOtherwise, make sure that you are setting different values when creating the API client:
import { createAPIClient } from "@shopware/api-client";
import type { operations } from "@shopware/api-client/store-api-types";
import { ref } from "vue";
import type { ShopwareFrontendsOptions } from "./configure-api-client-2";
const ssrValue = "http://shopware";
const clientValue = "https://demo-frontends.shopware.store";
const options: ShopwareFrontendsOptions = {
endpoint: clientValue,
accessToken: "SWSCBHFSNTVMAWNZDNFKSHLAYW",
shopwareApiClient: {
timeout: 5000,
},
};
const contextToken = ref<string>();
const languageId = ref<string>();
const apiClient = createAPIClient<operations>({
baseURL: ssrValue || clientValue,
accessToken: options.accessToken,
fetchOptions: {
timeout: options.shopwareApiClient?.timeout || 5000,
},
contextToken: contextToken.value,
defaultHeaders: {
"sw-language-id": languageId.value,
},
});
export { apiClient };WARNING
If you need to redirect your media, you can use the shopware.yaml file to configure the main media URL. For more details, please visit this site.
Next steps
After your setup, you can follow our building guides to get started with Shopware Frontends