Migrating from 1.12.0 to SDK
If your project uses @vsf-enterprise/commercetools@1.12.0
, there are two possible update paths, namely, upgrading your project to use our SDK (recommended) or you may also stay with composables. Upgrading to the SDK will allow you to use the latest features Alokai has to offer.
Update path 1: Rewrite your repository to use VSF Commercetools SDK instead of composables
This is the recommended update path, as it moves your project to use the latest generation of VSF software - the SDK. All new version releases are built with the SDK in mind, while composables are considered legacy.
When switching to the SDK, it is expected that the user's storefront will stop using the composables and getters from the @vsf-enterprise/commercetools
package. Instead, the VSF framework-agnostic SDK should be used.
Before the migration, while still using composables, your Vue code for a product page may look like this:
<!-- MyProductPage.vue -->
<template> ... </template>
<script>
import { defineComponent, computed } from "@nuxtjs/composition-api"
import { useProduct, productGetters } from "@vsf-enterprise/commercetools"
export default defineComponent({
name: "ProductPage",
setup() {
const route = useRoute()
const { products, search, error, loading } = useProduct("products")
const product = computed(
() =>
productGetters.getFiltered(products.value, {
skus: [route.value.query.productId],
})[0]
)
// Other possible used getters:
// const options = computed(() => productGetters.getAttributes(products.value, ['color', 'size']));
// const configuration = computed(() => productGetters.getAttributes(product.value, ['color', 'size']));
// const categories = computed(() => productGetters.getCategorySlugs(product.value));
// const breadcrumbs = computed(() => productGetters.getBreadcrumbs(product.value)
// .map(breadcrumb => ({ ...breadcrumb, link: localePath(breadcrumb.link) })));
return {
products,
search,
error,
loading,
product,
}
},
})
</script>
And after the migration - already using the new VSF Commercetools SDK, it may look like this:
<template>
<div>
<div>Product: {{ product && "Got a product!: " + product.id }}</div>
<div>Loading: {{ loading && "loading" }}</div>
<button @click="search(productId)">Search</button>
</div>
</template>
<script>
import { sdk } from "../sdk.config.js" // will be shown how to configure later
import {
defineComponent,
useRoute,
computed,
ref,
} from "@nuxtjs/composition-api"
export default defineComponent({
name: "ProductPage",
setup() {
const route = useRoute()
const productId = route.value.query.productId
const products = ref([])
const product = computed(() => products.value?.products?.results?.[0])
const loading = ref(false)
const error = ref(null)
const search = async (inputProductId) => {
try {
loading.value = true
error.value = null
const receivedProducts = await sdk.ct.getProduct({
skus: [inputProductId],
})
products.value = receivedProducts
loading.value = false
} catch (e) {
loading.value = false
error.value = e
}
}
return {
product,
productId,
loading,
error,
search,
}
},
})
</script>
The useProduct
composable in the first example provided dynamically updating loading
, products
and error
Vue refs which changed their value based on what happened when calling useProduct
's search
method:
const { products, search, error, loading } = useProduct("products")
As you can see in the second, post-migration example that uses the SDK - VSF no longer handles this framework-specific Vue logic. The dynamic error, loading and data refs are implemented around it by hand by the programmers.
const receivedProducts = await sdk.ct.getProduct({ id: productId })
It only fetches products from the Alokai middleware, which queries the Commercetools API. The arguments to the SDK methods are fully typed and allow for filtering, using custom queries etc., so there's no need to learn the raw Commercetools API yourself. Implementing framework-specific logic, such as the error
and loading
refs are now responsibilities of the programmer using the SDK when developing their storefront.
Removal of @vue-storefront/core and dependence on Nuxt plugins
When migrating to the SDK, you will also need to remove the @vue-storefront/core
package. This means you will need to migrate from using methods useVSFContext
and onSSR
.
Here are some common use cases that you'll need to migrate from:
- Case: Login guards that use
$vsf.$ct.api.isLoggedIn()
: Migration: Usesdk.ct.isLoggedIn()
- Case: URLs that use
addBasePath()
from the@vue-storefront/core
package Migration: Prepend the result of callinguseRouter().options.base
to the URLs - Case:
useVSFContext().$ct.config.countries
Migration: If your store is restricted to particular countries, set them in Merchant Center on the URLhttps://mc.[region].gcp.commercetools.com/[project name]/settings/project/stores/[store id]
, then usesdk.ct.getStores()
to fetch those countries. - Case:
onSSR
Migration: UseuseAsync
anduseFetch
from@nuxtjs/composition-api
Getters are removed in the SDK
Getters that were used in the composable approach no longer exist in the SDK approach. After migrating to the SDK, simply access the property returned by the SDK method.
- const { products, search, error, loading } = useProduct('products');
- const product = computed(() => productGetters.getFiltered(products.value, { skus: [route.value.params.productId] })[0]);
+ const products = ref(null);
+ products.value = await sdk.ct.getProduct({ id: productId });
+ const product = computed(() => products.value.products.results?.[0])
Reducing repetitive logic
The code in the post-migration example is presented in its simplest form. Of course - if viable for your case - you could re-implement VueUse's useAsyncState in your code-base to abstract away the repetitive error and loading handling. See the example below. Please be aware that the word "re-implement" is used because useAsyncState
relies on native Vue Composition API, while you may be using @nuxtjs/composition-api
.
Migration steps
- Remove the following packages:
yarn remove @vsf-enterprise/commercetools @vue-storefront/http-cache @vue-storefront/nuxt
- Remove the VSF Nuxt plugins from
nuxt.config.js
.
The SDK no longer uses the Nuxt context to contact the middleware. The SDK queries the middleware directly, such ashttp://localhost:4000/ct/getProduct
.buildModules: [ '@nuxtjs/pwa', - [ - '@vsf-enterprise/commercetools/nuxt', - ... - ], - [ - '@vue-storefront/nuxt', - ... - ], ], modules: [ - [ - '@vue-storefront/http-cache/nuxt', - ... - ] ]
- Install the
@vue-storefront/sdk
,@vue-storefront/middleware
,@vsf-enterprise/commercetools-sdk
and@vsf-enterprise/commercetools-api
packagesyarn add @vue-storefront/sdk @vsf-enterprise/commercetools-sdk @vsf-enterprise/commercetools-api @vue-storefront/middleware
{type='info'}
@vsf-enterprise/commercetools-api
since version1.19.0
requires Node version=> 16 && < 19
If not already present in your package.json, install these missing Nuxt plugins explicitly:yarn add @nuxtjs/composition-api@0.29.3 @nuxt/typescript-build @nuxt/core @nuxtjs/style-resources
@nuxtjs/composition-api version is explicit because it seems that the latest version (0.33.1) does not attach the return value ofsetup()
to the Vue instance.
In case you run into issues withnode-gyp
missing when installing, please runyarn global add node-gyp
and try again. - Upgrade the
nuxt
package to at least2.16.2
. Without it, you will get errors regarding hash generation when using Node 18.
yarn add nuxt@^2.16.2
- Update your transpilation configuration so that the newly added packages in point 3 build. This is because those packages use the new "nullish coalescing" operators in ECMAScript and your current build configuration may not support them.
// nuxt.config.js
...,
build: {
babel: {
plugins: [
['@babel/plugin-proposal-private-methods', { loose: true }],
+ '@babel/plugin-proposal-optional-chaining',
+ '@babel/plugin-proposal-nullish-coalescing-operator',
],
},
+ transpile: ['@vsf-enterprise/commercetools-sdk', '@vue-storefront/sdk'],
}
...
Make sure to install those Babel plugins as well:
yarn add @babel/plugin-proposal-optional-chaining @babel/plugin-proposal-nullish-coalescing-operator
Alternatively, you can just use the @nuxt/babel-preset-app
:
yarn add @nuxt/babel-preset-app
then:
// nuxt.config.js
...,
build: {
babel: {
+ presets(env, [ preset, options ]) {
+ return [
+ [ "@nuxt/babel-preset-app", options ]
+ ]
}
},
+ transpile: ['@vsf-enterprise/commercetools-sdk', '@vue-storefront/sdk'],
}
- If your
package.json
file has theengines
field, update it to reflect the currently supported Node versions:"engines": { - "node": ">=14 <=16" + "node": ">=16 <19" },
- In the repository root (or the
src/
folder), create asdk.config.ts
(or.js
) file and fill it with the contents shown below.import { ctModule } from "@vsf-enterprise/commercetools-sdk" import { initSDK, buildModule } from "@vue-storefront/sdk" const sdkConfig = { commerce: buildModule(ctModule, { apiUrl: "http://localhost:8181/ct", ssrApiUrl: "http://localhost:8181/ct", }), } export const sdk = initSDK(sdkConfig)
Make sure that theapiUrl
andssrApiUrl
match the extension name that you used for the Commercetools integration in theintegrations
property inmiddleware.config.js
:// middleware.config.js module.exports = { integrations: { ct: { location: '@vsf-enterprise/commercetools-api/server',
If the key in theintegrations
object for you is for examplecommercetools
instead ofct
, theapiUrl
andssrApiUrl
properties should end with/commercetools
.
Once thesdk.config.ts
file is created, you can then import the SDK to use in place of composables and getters in your.vue
components as previously shown in the introduction to this document:import { sdk } from "../sdk"; ... const products = await sdk.ct.getProduct({ id: productId }); ...
- Remove all imports that use
from '@vsf-enterprise/commercetools'
and@vue-storefront/core
, because we deleted these packages in point 1.
This means you will have to rewrite your code from the Vue composable-based approach to the framework-agnostic SDK based approach, as shown in the introduction at the top of this document.
Update path 2: Stay with composables and update to @vsf-enterprise/commercetools@2.x.x
Using this update path will allow you to use a newer version of the API client.
@vsf-enterprise/commercetools@1.12.0
- uses@vsf-enterprise/commercetools-api@1.12.0
@vsf-enterprise/commercetools@2.0.3
- uses@vsf-enterprise/commercetools-api@~1.21.2
In addition, this is update path allows you to use @vsf-enterprise/commercetools
with Node versions >= 16 (which includes Node 18).
Migration steps
- Update the
@vsf-enterprise/commercetools
package to 2.0.3
yarn add @vsf-enterprise/commercetools@2.0.3
- Upgrade the
nuxt
package to at least2.16.2
. Without it, you will get errors regarding hash generation when using Node 18.
$ yarn add nuxt@^2.16.2
- Update the Nuxt plugins to the versions that support Node 18. Only run those commands that update the packages that you actually have installed in your repository.
Only run those commands that update the packages that you actually have installed in your repository.
yarn add @vue-storefront/middleware@2.8.0
yarn add @vue-storefront/nuxt@2.8.0
yarn add @vue-storefront/nuxt-theme@2.8.0
yarn add @vue-storefront/cache@2.8.0
yarn add @vue-storefront/http-cache@2.8.0
yarn add @vue-storefront/health-check@2.8.0
If due to a mistake you have @vue-storefront/core installed explicitly (shouldn't happen)
yarn add @vue-storefront/core@2.8.0
- If your
package.json
file has theengines
field, update it to reflect the currently supported Node versions:"engines": { - "node": ">=14 <=16" + "node": ">=16 <19" },
If you use the useStore
composable be aware that:
- The first argument to
useStores().load(...)
now has the type StoresWhereSearch. The new format is:
- useStore().load({ customQuery: { someMethod: 'some-custom-query' })
+ useStore().load({ id: 'id' });
+ useStore().load({ ids: ['id1', 'id2'] });
+ useStore().load({ key: 'key' });
- The argument type change also means that
useStores().load()
method no longer accepts acustomQuery
parameter.
If you rely on the CustomQuery
type, you'll need to update the package that it's imported from:
- import { CustomQuery } from '@vue-storefront/core';
+ import { CustomQuery } from '@vsf-enterprise/commercetools-api';
If after upgrading to v2.x you still intend to use Node 16 instead of the newer Node 18, please make sure to set the NODE_OPTIONS=--openssl-legacy-provider
environment variable when launching your application. Otherwise, the launching will fail with an error. This workaround would not be necessary when using Webpack v5, however Nuxt 2 only supports up to Webpack 4. If you want to avoid this workaround, consider upgrading to Nuxt 3 and the Alokai SDK (composables are not compatible with Nuxt 3).