# Upgrading to 1.7.0

# Introduction

Hi. With this version, we're introducing some significant performance optimization like new improved typings, the new Node version or conditional rendering removal, finally build modern mode for client.

# Upgrade to Node 12 or 14

We have recommended using Node 12 or higher for a few months now. It's mandatory starting with this release because @vsf-enterprise/commercetools-api and @vsf-enterprise/commercetools packages are now targeting ES2019 syntax, supported fully in Node 12+.

At this moment, we don't support Node versions higher than 14.

# Update import paths of types generated from commercetools GraphQL API

You might have noticed that some of the types exported from the @vsf-enterprise/commercetools-api represent data accepted and returned from the commercetools GraphQL API. We thought it would be easier to differentiate our types from those generated from the API if they come from two different packages.

For this reason, we introduced the new @vsf-enterprise/commercetools-types package. It only contains types generated from the commercetools GraphQL API and nothing more.

The @vsf-enterprise/commercetools-api package only includes types for the Server Middleware API, such as parameters accepted and data returned from API endpoints and default GraphQL queries sent to the commercetools GraphQL API.

You can refer to the API Reference for more details.

- import type { Customer } from '@vsf-enterprise/commercetools-api`;
+ import type { Customer } from '@vsf-enterprise/commercetools-types`;

# Update deprecated types

We refactored most types in @vsf-enterprise/commercetools-api and @vsf-enterprise/commercetools packages to improve coding suggestions. We marked most of the types we no longer use as deprecated with comments indicating the new type that you should use instead. Most IDEs should highlight deprecated types — you can click them to go to the type declaration file for more information.

We will remove deprecated types in version 1.7.0.

# Upgrade @storefront-ui/vue package to version 0.13.0

With the new Storefront UI version, we bring some performance improvements however, you need to make some changes to your components.

# components/CartSidebar

  <SfSidebar
   class="sf-sidebar--right"
   v-e2e="'sidebar-cart'"
   :visible="isCartSidebarOpen"
   :title="$t('My Cart')"
   @close="toggleCartSidebar"
   :persistent="hasNotifications"
+  position="right"
  >
# components/WishlistSidebar

  <SfSidebar
   class="sf-sidebar--right"
   v-e2e="'sidebar-wishlist'"
   :visible="isWishlistSidebarOpen"
   :title="$t('My wishlist')"
   @close="toggleWishlistSidebar"
   :persistent="hasNotifications"
+  position="right"
  >

# Remove mobileObserver

With this version we're getting rid of all the conditional rendering. This means that we're not using mobileObserver utility anymore. It was removed along with the new Storefront UI version. Please follow these steps to cover all the necessary changes. This contributes to our full CDN optimization.

# components/AppFooter

data() {
  return {
-  isMobile: false,
-  desktopMin: 1024
  }
}
# components/AppHeader

 <template #navigation>
- <HeaderNavigation :isMobile="isMobile">
+ <HeaderNavigation>
 </template>

...

- import {
-  mapMobileObserver,
-  unMapMobileObserver
- } from '@storefront-ui/vue/src/utilities/mobile-observer.js';

...

- const isMobile = ref(mapMobileObserver().isMobile.get());

...

watch(() => term.value, (newVal, oldVal) => {
-  const shouldSearchBeOpened = (!isMobile.value && term.value.length > 0) && ((!oldVal && newVal) || (newVal.length !== oldVal.length && isSearchOpen.value === false));
-  if (shouldSearchBeOpened) {
+  if (term.value.length > 0 && ((!oldVal && newVal) || (newVal.length !== oldVal.length && isSearchOpen.value === false))) {
    isSearchOpen.value = true;
  }
});

...

- onBeforeUnmount(() => {
-  unMapMobileObserver();
- });

...

return {
  ...
- isMobile  
}
# components/Headernavigation

  <template>
-  <div class="sf-header__navigation desktop" v-if="!isMobile">
-   <SfHeaderNavigationItem
-     v-for="category in categories"
-     :key="category.id"
-     class="nav-item"
-     v-e2e="`app-header-url_${category.slug}`"
-     :label="category.name"
-     :link="localePath(`/c/${category.slug}`)"
-   />
-  </div>
-  <SfModal v-else :visible="isMobileMenuOpen">
+   <div class="header-navigation">
+    <div class="sf-header__navigation desktop-only">
+      <SfHeaderNavigationItem
+        v-for="category in categories"
+        :key="category.id"
+        class="nav-item"
+        v-e2e="`app-header-url_${category.slug}`"
+        :label="category.name"
+        :link="localePath(`/c/${category.slug}`)"
+      />
+    </div>
+   <SfModal class="smartphone-only" :visible="isMobileMenuOpen">
      <SfList>
        <SfListItem
          v-for="category in categories"
          :key="category.id"
          class="nav-item sf-header-navigation-item"
          v-e2e="`app-header-url_${category.slug}`"
        >
          <SfMenuItem
            :label="category.name"
            class="sf-header-navigation-item__menu-item"
            :link="localePath(`/c/${category.slug}`)"
            @click.native="toggleMobileMenu"
          />
        </SfListItem>
      </SfList>
    </SfModal>
+  </div>
  </template>

...

- props: {
-  isMobile: {
-   type: Boolean,
-   default: false
-  }
- },
# components/InstagramFeed

  <template>
...
-   <SfImage v-if="isMobile" :src="'/homepage/imageAm.webp' | addBasePathFilter" alt="katherina_trn" :width="160" :height="160">katherina_trn</SfImage>
-   <SfImage v-else :src="'/homepage/imageAd.webp' | addBasePathFilter" alt="katherina_trn" :width="470" :height="470">katherina_trn</SfImage>
+   <SfImage
+     class="smartphone-only"
+     :src="'/homepage/imageAm.webp' | addBasePathFilter"
+     alt="katherina_trn"
+     :width="160"
+     :height="160"
+   >
+    katherina_trn
+   </SfImage>
+   <SfImage
+     class="desktop-only"
+     :src="'/homepage/imageAd.webp' | addBasePathFilter"
+     alt="katherina_trn"
+     :width="470"
+     :height="470"
+   >
+    katherina_trn
+   </SfImage>

...

-   <SfImage v-if="isMobile" :src="'/homepage/imageBm.webp' | addBasePathFilter" alt="katherina_trn" :width="160" :height="160">katherina_trn</SfImage>
-   <SfImage v-else :src="'/homepage/imageCd.webp' | addBasePathFilter" alt="katherina_trn" :width="470" :height="470">katherina_trn</SfImage>
+   <SfImage
+     class="smartphone-only"
+     :src="'/homepage/imageBm.webp' | addBasePathFilter"
+     alt="katherina_trn"
+     :width="160"
+     :height="160"
+   >
+    katherina_trn
+   </SfImage>
+   <SfImage
+     class="desktop-only"
+     :src="'/homepage/imageCd.webp' | addBasePathFilter"
+     alt="katherina_trn"
+     :width="470"
+     :height="470"
+   >
+    katherina_trn
+   </SfImage>

...

-   <SfImage v-if="isMobile" :src="'/homepage/imageCm.webp' | addBasePathFilter" alt="katherina_trn" :width="160" :height="160">katherina_trn</SfImage>
-   <SfImage v-else :src="'/homepage/imageBd.webp' | addBasePathFilter" alt="katherina_trn" :width="470" :height="470">katherina_trn</SfImage>
+   <SfImage
+     class="smartphone-only"
+     :src="'/homepage/imageCm.webp' | addBasePathFilter"
+     alt="katherina_trn"
+     :width="160"
+     :height="160"
+   >
+    katherina_trn
+   </SfImage>
+   <SfImage
+     class="desktop-only"
+     :src="'/homepage/imageBd.webp' | addBasePathFilter"
+     alt="katherina_trn"
+     :width="470"
+     :height="470"
+   >
+    katherina_trn
+   </SfImage>

...

-   <SfImage v-if="isMobile" :src="'/homepage/imageDm.webp' | addBasePathFilter" alt="katherina_trn" :width="160" :height="160">katherina_trn</SfImage>
-   <SfImage v-else :src="'/homepage/imageDd.webp' | addBasePathFilter" alt="katherina_trn" :width="470" :height="470">katherina_trn</SfImage>
+   <SfImage
+     class="smartphone-only"
+     :src="'/homepage/imageDm.webp' | addBasePathFilter"
+     alt="katherina_trn"
+     :width="160"
+     :height="160"
+   >
+    katherina_trn
+   </SfImage>
+   <SfImage
+     class="desktop-only"
+     :src="'/homepage/imageDd.webp' | addBasePathFilter"
+     alt="katherina_trn"
+     :width="470"
+     :height="470"
+   >
+    katherina_trn
+   </SfImage>
  </template>

...

- import {
-  mapMobileObserver,
-  unMapMobileObserver
- } from '@storefront-ui/vue/src/utilities/mobile-observer.js';

...

-  computed: {
-    ...mapMobileObserver()
-  },
-  beforeDestroy() {
-    unMapMobileObserver();
-  }
# pages/MyAccount

- import { computed, onBeforeUnmount, useContext, useRouter, useRoute } from '@nuxtjs/composition-api';
+ import { computed, useContext, useRouter, useRoute } from '@nuxtjs/composition-api';
- import {
-  mapMobileObserver,
-  unMapMobileObserver
- } from '@storefront-ui/vue/src/utilities/mobile-observer.js';

...

- const isMobile = computed(() => mapMobileObserver().isMobile.get());

const activePage = computed(() => {
  const { pageName } = route.value.params;
  if (pageName) {
    return (pageName.charAt(0).toUpperCase() + pageName.slice(1)).replace('-', ' ');
  }
-  else {
-    return !isMobile.value ? i18n.t('My profile') : '';
-  }
});

-  onBeforeUnmount(() => {
-   unMapMobileObserver();
-  });

# Use --modern=client mode

From now on, with application build we're using Nuxt modern mode just for client side. More about this you can find here (opens new window).

# package.json

- "build": "nuxt build -m",
- "build:analyze": "nuxt build -a -m",
- "start": "nuxt start",
+ "build": "nuxt build --modern=client",
+ "build:analyze": "nuxt build -a --modern=client",
+ "start": "nuxt start --modern=client",