All Release Notes

Custom Applications v17

14 October 2020
Announcement
GeneralDevelopment

The Application Kit packages have been released as a new major version v17. One of the most important changes in this release is about migrating to the new Apollo Client v3.

This release contains breaking changes.

Follow the steps below to migrate your Custom Application to the new versions.

Migrating to Apollo Client v3

Migrating to the new Apollo Client v3 requires some important migration steps.

Migrating Apollo imports

Apollo ships now with a single package @apollo/client instead of multiple ones.

For Custom Applications this means that the peer dependencies apollo-client and react-apollo are now replaced with the new peer dependency of @apollo/client.

This is all you need to do to migrate to the latest version of Apollo, including of course updating the Apollo imports.

About the new Apollo Cache

With Apollo v3, the Apollo in-memory cache got some improvements as well, resulting in some breaking changes. Please make sure to read this document to understand the changes.

Depending on the GraphQL queries and mutations used by your Custom Application, it might be that the caching behavior of those queries needs to be adjusted. For example if objects do not have an id field as identifier, or if Apollo cannot automatically merge two objects that have different fields shape, and so on.

If that is the case, you need to configure the Apollo cache according to your needs, as only you know what the best caching strategy for your Custom Application is.

To enable you to do so, the <ApplicationShell> component now accepts an apolloClient prop, that allows you to configure your own instance of the Apollo client with the custom cache configuration.

The @commercetools-frontend/application-shell package exposes a createApolloClient function that allows you to create a new Apollo client pre-configured with some important defaults (for example Apollo links, some basic cache policies, etc.).

import {
createApolloClient,
ApplicationShell,
} from '@commercetools-frontend/application-shell';
const apolloClient = createApolloClient({
cache: {
// Your custom configuration, according to the Apollo cache documentation.
// https://www.apollographql.com/docs/react/caching/cache-configuration/
},
});
const Application = () => {
return (
<ApplicationShell
apolloClient={apolloClient}
// ...other props
/>
);
};
Changes about Apollo query variables and context

Previously, to perform GraphQL requests to the Merchant Center API Gateway, you would need to specify request metadata options such as the GraphQL Target.

These values had to be specified in the query variables object, which the built-in Merchant Center Apollo HTTP Link would parse and assign it to the request as HTTP headers. We call these options request context.

However, with a more stable support for the context option in Apollo Client, we can pass the request metadata options to the context object instead of the variables object.

const { loading, data, error } = useQuery(MyQuery, {
- variables: {
+ context: {
target: GRAPHQL_TARGETS.COMMERCETOOLS_PLATFORM,
},
});

The request context options include:

  • target
  • projectKey

Passing the request metadata to the variables object still works for backwards compatibility but it is recommended to use the context object instead.

Enforcing a valid context object

The recommended and preferred way of passing request context is to use the context object. To improve the TypeScript support and auto-completion for the request context options, the @commercetools-frontend/application-shell package now exports new React hooks. Note that autocompletion is possible, even if you are not using TypeScript.

  • useMcQuery
  • useMcLazyQuery
  • useMcMutation

These hooks are thin wrappers around the original Apollo hooks and have the same API, with a minor difference. Namely, the context object is properly typed to conform with the Merchant Center request context instead of any.

-import { useQuery } from '@apollo/client/react';
+import { useMcQuery } from '@commercetools-frontend/application-shell';
-const { loading, data, error } = useQuery(MyQuery, {
+const { loading, data, error } = useMcQuery(MyQuery, {
context: {
target: GRAPHQL_TARGETS.COMMERCETOOLS_PLATFORM,
},
});

Changes about the mc-scripts CLI

Removing deprecated options from compile-html

Previously deprecated CLI options such as --env, --csp, --headers, have been removed.

Additionally, the CLI flag --use-local-assets has been removed as well. As such the default behavior of mc-scripts compile-html changed to compile the assets locally.

When running the mc-scripts compile-html command, the index.html is compiled for production usage and it lives in the public folder, together with the other static assets. This is all you need to deploy your application. You can decide to deploy the Custom Application statically to one of the popular cloud providers, or serve the files on your own using a static server.

For example, to run locally the Custom Application using the production bundles:

NODE_ENV=production MC_APP_ENV=development dotenv -- \
mc-scripts compile-html \
--transformer @commercetools-frontend/mc-dev-authentication/transformer-local.js
mc-scripts serve
Removing the mc-http-server package

The @commercetools-frontend/mc-http-server package has been deprecated and will not receive any updates.

With the usage of the compile-html command there is no need to have a pre-configured HTTP server anymore. If you are using this package, we recommend to use any other HTTP server package to serve your static files.

Remember that after building your production bundles you need to compile the Custom Application for production usage.

New command serve

We added a new command mc-scripts serve that can be used to start your Custom Application locally in production mode after it has been compiled.

The command starts an HTTP server to serve the static assets from the public folder.

This command should only be used locally to test the Custom Application in production mode, as it contains the development routes for /login and /logout. Do not use this command to serve your Custom Application in production.

Before:

package.jsonjson
{
"start:prod:local": "NODE_ENV=production MC_APP_ENV=development dotenv -- mc-http-server --use-local-assets"
}

After:

package.jsonjson
{
"compile-html:local": "NODE_ENV=production MC_APP_ENV=development dotenv -- mc-scripts compile-html --transformer @commercetools-frontend/mc-dev-authentication/transformer-local.js",
"start:prod:local": "yarn compile-html:local && mc-scripts serve"
}
Removing the extract-intl command

The mc-scripts extract-intl command has been removed in favor of the official @formatjs/cli package.

We recommend to update your script to extract Intl messages to use the formatjs extract command.

Before:

package.jsonjson
{
"i18n:build": "mc-scripts extract-intl --output-path=$(pwd)/src/i18n/data 'src/**/!(*.spec).js' --build-translations"
}

After:

package.jsonjson
{
"extract-intl": "formatjs extract --format=$(pwd)/intl-formatter.js --out-file=$(pwd)/src/i18n/data/core.json 'src/**/!(*.spec).js'"
}

where the intl-formatter.js should be defined as something like this, depending on your translation tool's needs:

intl-formatter.jsJavaScript
// https://formatjs.io/docs/tooling/cli#extraction
exports.format = function format(extractedMessages) {
return (
Object.keys(extractedMessages)
// transform strings to lowercase to imitate phraseapp sorting
.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()))
.reduce(
(allMessages, messageId) => ({
...allMessages,
// Return a simple key/value JSON object.
[messageId]: extractedMessages[messageId].defaultMessage,
}),
{}
)
);
};

Changes about the experimentalRenderAppWithRedux from test utils

The experimental render method experimentalRenderAppWithRedux from the test-utils has been removed.

Instead, you should pass the disableApolloMocks option to the renderApp and renderAppWithRedux methods. When this option is set to true, the real ApolloProvider is rendered instead of Apollo's MockProvider.

This is useful if you want to mock requests at the network level, for example when using Mock Service Worker.

Additionally, you can also pass a custom apolloClient instance together with the disableApolloMocks option. This is only needed when your Custom Application uses a custom apolloClient, for example for configuring the cache policies.

Removing the deprecated options from application-shell

The @commercetools-frontend/application-shell package no longer exports the deprecated AsyncChunkLoader and handleApolloErrors.

Additionally, the deprecated prop trackingEventWhitelist of the <ApplicationShell> component has been removed as well.