Skip to main content

Upgrade to 17.0.0

Why you should upgrade

This upgrade includes a new market selector panel and product review component.

See release notes for more information

Pre-requisites

Before upgrading to 17, make sure you have already upgraded to 16. See guide here

Steps

Update .env

  • Update your .env file. Here is an outline of what variables your local .env-file should contain.
Important

Note that FALLBACK_MARKET_ALIAS is used instead of FALLBACK_MARKET_ID:

.env.example
  // Always needed
IMAGE_SERVER= *** (URL)
API_KEY= *** (STRING)
API_ENDPOINT= *** (URL)
AUTH_ENDPOINT= *** (URL)
SIGN_ENDPOINT= *** (URL)
BASE_URL= *** (URL including http)
FALLBACK_CHANNEL_ID= *** (STRING in format "number|countryCode", e.g. "1|se")
FALLBACK_MARKET_ALIAS= *** (STRING in format "countryCode", e.g. "se")
DEFAULT_LOCALE= *** (STRING in format "langCode", e.g. "sv")
APPINSIGHTS_INSTRUMENTATION_KEY= *** (STRING)

// Only needed when using "diffrentDomains", with one tld per language or
// add only one domain here to leave market and language out of path
DOMAINS= *** (STRING in format "langCode|urlWithoutHttp,langCode|urlWithoutHttp", e.g. "sv|www.site.se,fi|www.site.fi")

// Only needed when you want to use GTM
GTM_ID= *** (STRING)

// Only needed to use Nosto integration
NOST_API_APPS_KEY= *** (STRING)
NOSTO_ACCOUNT_ID= *** (STRING)

Update Dockerfile

  • Update Dockerfile to use DOMAINS and FALLBACK_MARKET_ALIAS. Remove previous used DOMAIN variables:
Dockerfile
...
// Remove this, no longer needed
ARG DOMAIN_SV=#{DomainSv}#
ARG DOMAIN_EN=#{DomainEn}#

// Add this
ARG FALLBACK_MARKET_ALIAS=#{FallbackMarketAlias}#
ARG DOMAINS=#{Domains}#
...
// Remove this, no longer needed
ARG DOMAIN_SV
ARG DOMAIN_EN

// Add this
ARG FALLBACK_MARKET_ALIAS
ARG DOMAINS
...
// Remove this, no longer needed
ENV DOMAIN_SV=${DOMAIN_SV}
ENV DOMAIN_EN=${DOMAIN_EN}

// Add this
ENV FALLBACK_MARKET_ALIAS=${FALLBACK_MARKET_ALIAS}
ENV DOMAINS=${DOMAINS}
...

Update nuxt.config.js

  • Replace the fallbackMarketId with fallbackMarketAlias:

replace:

nuxt.config.js
const fallbackMarketId = process.env.FALLBACK_MARKET_ID;

with:

nuxt.config.js
const fallbackMarketAlias = process.env.FALLBACK_MARKET_ALIAS;
  • Add domain settings like this:
nuxt.config.js
// Set the domain settings and market settings based on if env-variable DOMAINS exists
// Default settings for multi market / multi language

let domainSettings = {
differentDomains: false,
strategy: "prefix",
};
let domainUrls = null;

// Default settings for market for publicRuntimeConfig
let marketSettings = {
isMultiLanguage: true,
marketInPath: true,
};

if (process.env.DOMAINS) {
const domains = process.env.DOMAINS.split(",");

domainUrls = domains
?.map((domain) => {
const domainArr = domain?.split("|");
return {
[domainArr[0]]: domainArr[1] || "",
};
})
.reduce((result, item) => {
const key = Object.keys(item)[0];
result[key] = item[key];
return result;
}, {});

// If using DOMAINS, turn off multilang and marketInPath
marketSettings = {
isMultiLanguage: false,
marketInPath: false,
};

// If site should have only language prefix and no market prefix, remove the following declaration
domainSettings = {
differentDomains: false,
strategy: "no_prefix",
};

if (domains.length > 1) {
// If more than one domain, set diffrentDomains to true
domainSettings = {
differentDomains: true,
};
}
}
  • Add the fallbackMarketAlias to the listPageInfo query:
nuxt.config.js
    ...
query listPageInfo {
listPageInfo(
alias: "frontpage",
channelId: "${fallbackChannelId}",
marketId: "${fallbackMarketAlias}"
) {
meta {
description
title
}
}
}
...
  • Add getMarketsQuery and fetch markets in the export default function:
nuxt.config.js
export default async () => {
...
// Get fallback markets
const getMarketsQuery = await apolloClient.query({
query: gql`
query channel {
channel(channelId: "${fallbackChannelId}") {
defaultMarketId
markets {
id
defaultLanguageId
alias
virtual
onlyDisplayInCheckout
groupKey
allowedLanguages {
id
name
code
}
country {
name
code
}
currency {
name
code
}
}
}
}
`,
context: {
headers: {
"X-ApiKey": process.env.API_KEY,
},
},
});
const markets = await getMarketsQuery.data.channel.markets;
...
}
  • In the @nuxtjs/i18n module:

    • Remove the strategy and the differentDomains properties, and add the domainSettings instead.
    • In the locales array, remove the flag and currency properties from each object.
    • Add the domain property to each object.
    • Update the objects in the pages object.

    Should look something like this:

nuxt.config.js
modules: [
// Doc: https://github.com/nuxt-community/pwa-module
'@nuxtjs/pwa',
[
// Doc: https://github.com/nuxt-community/i18n-module
'@nuxtjs/i18n',
{
baseUrl: process.env.BASE_URL,
seo: false,
locales: [
{
code: 'en',
iso: 'en-US',
file: 'en-US.js',
name: 'English',
domain: domainUrls?.en || '' // Only matters if diffrentDomains are used
},
{
code: 'sv',
iso: 'sv-SE',
file: 'sv-SE.js',
name: 'Swedish',
domain: domainUrls?.sv || '' // Only matters if diffrentDomains are used
},
{
code: 'nb',
iso: 'nb-NO',
file: 'nb-NO.js',
name: 'Norsk',
domain: domainUrls?.nb || '' // Only matters if diffrentDomains are used
},
{
code: 'nn',
iso: 'nn-NO',
file: 'nb-NO.js',
name: 'Norsk',
domain: domainUrls?.nn || '' // Only matters if diffrentDomains are used
},
{
code: 'da',
iso: 'da-DK',
file: 'da-DK.js',
name: 'Dansk',
domain: domainUrls?.da || '' // Only matters if diffrentDomains are used
},
{
code: 'fi',
iso: 'fi-FI',
file: 'fi-FI.js',
name: 'Finska',
domain: domainUrls?.fi || '' // Only matters if diffrentDomains are used
}
],
langDir: 'languages/',
defaultLocale: process.env.DEFAULT_LOCALE,
lazy: true,
vueI18n: {
fallbackLocale: process.env.DEFAULT_LOCALE
},
detectBrowserLanguage: false,
parsePages: false,
pages: {
'checkout/index': {
sv: '/kassan',
en: '/checkout',
da: '/kassen',
fi: '/kassa',
nb: '/kassen'
},
'account/orders': {
sv: '/mina-sidor/ordrar',
en: '/my-account/orders',
da: '/min-konto/bestillinger',
fi: '/tilini/tilaukset',
nb: '/min-konto/bestillinger'
},
'account/settings': {
sv: '/mina-sidor/installningar',
en: '/my-account/settings',
da: '/min-konto/indstillinger',
fi: '/tilini/asetukset',
nb: '/min-konto/innstillinger'
},
'account/balance': {
sv: '/mina-sidor/saldo',
en: '/my-account/balance',
da: '/min-konto/saldo',
fi: '/tilini/saldo',
nb: '/min-konto/saldo'
},
'favorites/index': {
sv: '/favoriter',
en: '/favorites',
da: '/favoritter',
fi: '/suosikkeja',
nb: '/favoritter'
},
'brands/index': {
sv: '/varumarken',
en: '/brands',
da: '/varemaerker',
fi: '/tavaramerkkeja',
nb: '/varemerker'
}
},
...domainSettings // Instead of 'strategy' and 'differentDomains'
}
]
  • In publicRuntimeConfig: Remove the isMultiLanguage and marketInPath properties. Replace the fallbackMarketId with fallbackMarketAlias, and Add the markets settings:
nuxt.config.js
publicRuntimeConfig: {
...
// isMultiLanguage remove this
// marketInPath remove this

fallbackMarketAlias, // Instead of fallbackMarketId
...marketSettings, // Add this
markets, // Add this ... }
  • Also add the showProductReviewSectionarketInPath and showStarsInProductReviewForm settings to publicRuntimeConfig:
nuxt.config.js
publicRuntimeConfig {
...
showProductReviewSection: true,
showStarsInProductReviewForm: true // it requires showProductReviewSection to be true
...
}

Implementation

Note

Changes has been made to following mixins:

  • MixCheckout.js: (Extensive changes, check out file in Ralph-UI)

  • MixConfirmPage.js: (added variable checkoutMarket to mutation completeCart and query confirmCartQuery)

  • MixGlobalInit.js: (Now using getMarketsQuery)

  • MixListPage.js: (using $store.state.channel.id instead of $store.state.channelId)

  • MixNostoSection.js: (changed name from CaNostoSection to MixNostoSection)

  • MixDatalayer.js, MixAddToCart.js, MixNumberFormat.js, MixProductCard.js, MixProductPage.js and MixUpdateCart.js: (Using getters[channel/currentCurrency] instead of getters.getCurrency)

    If you have overriden any of these files and run into any problems, try to update the files.

  • Add new file channel.js to your store folder:
/store/channel.js
import { state, getters, mutations, actions } from "channel";

export default {
state,
getters,
mutations,
actions,
};
  • Add @mixin scrollbarStyle to /styles/helpers/_layout.scss:
/styles/helpers/_layout.scss
...
@mixin scrollbarStyle($color: $c-medium-gray, $hover: $c-darkest-gray) {
scrollbar-color: $color transparent;
scrollbar-width: thin;

&::-webkit-scrollbar {
background-color: transparent;
width: $px16 * 0.35;
height: $px16 * 0.35;
}

&::-webkit-scrollbar-track {
border-radius: 100vw;
}

&::-webkit-scrollbar-thumb {
background-color: $color;
border-radius: 100vw;
}

&::-webkit-scrollbar-thumb:hover {
background-color: $hover;
}
}
...
  • Add CaMarketPanel to /layouts/default.vue
/layouts/default.vue
<template>
<div class="ca-layout-default" :class="modifiers">
...
<LazyCaMarketPanel
v-if="$store.state.channel.markets.length > 1"
mode="advanced"
/>
...
</div>
</template>
  • Add CaMarketSelectorButton (replaces CaCountrySelectorPanel) in CaSecondaryNav.vue and CaTopBar.vue (or wherever you prefer to place it).
/components/molecules/CaSecondaryNav/CaSecondaryNav.vue
<template>
<ul class="ca-secondary-nav">
...
<CaSecondaryNavItem>
<CaMarketSelectorButton />
</CaSecondaryNavItem>
...
</ul>
</template>
/components/organisms/CaTopBar/CaTopBar.vue
<template>
<div class="ca-top-bar" :class="{ 'ca-top-bar--undistracted': undistracted }">
...
<CaMarketSelectorButton
v-show="!undistracted"
class="ca-top-bar__lang-switcher only-computer"
/>
...
</div>
</template>
  • Updates to CaCheckout.vue:
    • Use selectableMarkets instead of markets.
    • Use setCheckoutMarket($event) instead of setmarketId($event).
    • Use !currentMarket instead of !marketId.
/components/organisms/CaCheckout/CaCheckout.vue
<template>
<div>
...
<CaCheckoutSection
v-if="
$store.getters['cart/totalQuantity'] &&
$config.checkout.showMultipleMarkets &&
selectableMarkets &&
selectableMarkets.length > 1
"
:loading="cartLoading"
>
<template #title>{{ $t('CHECKOUT_CHOOSE_COUNTRY') }}</template>
<CaCountrySelector
:data="selectableMarkets"
@input="setCheckoutMarket($event)"
/>
</CaCheckoutSection>

<CaCheckoutSection
v-if="$store.getters['cart/totalQuantity'] > 0"
:loading="shippingLoading"
:blocked="$config.checkout.showMultipleMarkets && !currentMarket"
>
...
</CaCheckoutSection>
</div>
</template>