Custom Applications v21
The Application Kit packages have been released with a new major version v21
.
This release contains breaking changes.
This version marks the release of new Custom Application features.
Furthermore, the Custom Application documentation has been restructured and updated to match the new status quo of Custom Applications. The Project-level legacy documentation remains available during the migration period in a separate location.
Follow the steps below to migrate your Application Kit packages to the new version.
New documentation
The Custom Applications documentation has been restructured and improved to provide a better developer experience. During the migration period the Project-level legacy documentation remains available for maintenance and reference purposes.
Supported Node.js versions
Support for Node.js v12
has been dropped. Recommended versions are v14
or v16
.
Upgrading ESLint to v8
ESLint has been upgraded to v8
as the minimal required version. Make sure to upgrade the eslint
package to v8
and any other ESLint-related package to their latest version.
The upgrade might include some rule changes and therefore some lint errors that need to be fixed.
Changes to peer dependencies
The following packages have updated their peer dependencies requirements:
@commercetools-frontend/application-shell
: requires@testing-library/react
version12.x
and@testing-library/react-hooks
version7.x
.@commercetools-frontend/cypress
: requirescypress
version8.x || 9.x
.@commercetools-frontend/jest-stylelint-runner
: requiresstylelint
version14.x
.
Changes to Custom Application config
The Custom Application config file has some new required fields.
env.development
oAuthScopes
*.defaultLabel
In addition to that, the menu link structure also changed a bit.
// Before{"menuLinks": {"icon": "HeartIcon","defaultLabel": "Starter","labelAllLocales": [],"permissions": [],"submenuLinks": [{"uriPath": "channels","defaultLabel": "Channels","labelAllLocales": [],"permissions": []}]}}// After{"icon": "${path:@commercetools-frontend/assets/application-icons/rocket.svg}","mainMenuLink": {"defaultLabel": "Starter","labelAllLocales": [],"permissions": [],},"submenuLinks": [{"uriPath": "channels","defaultLabel": "Channels","labelAllLocales": [],"permissions": []}]}
Note that there is a new required field defaultLabel
, which is used in case there is no localized label for the user's locale. If you don't need localized labels, you can leave the labelAllLocales
field empty and only use the defaultLabel
.
See Custom Application config for more information.
Referencing constants
The Custom Application config has support for additional file extensions. This allows us to reference certain variables in our Custom Application config and in other places of the application.
For example, we can define the entryPointUriPath
and the user permissions in a constants.js
file. The user permissions can be computed using the entryPointUriPathToPermissionKeys
function, to avoid defining them manually.
import { entryPointUriPathToPermissionKeys } from '@commercetools-frontend/application-shell/ssr';export const entryPointUriPath = 'avengers';export const PERMISSIONS = entryPointUriPathToPermissionKeys(entryPointUriPath);
The PERMISSIONS
variable contains a View
and Manage
properties, with the values being the computed values based on the entryPointUriPath
.
You can now reference these variables in the application code, as well as in the Custom Application config (using the .mjs
file extension):
import { entryPointUriPath, PERMISSIONS } from './src/constants';const config = {entryPointUriPath,mainMenuLink: {permissions: [PERMISSIONS.View],},// ...};export default config;
New login workflow
Starting the Custom Application locally now redirects you to the login page of the Merchant Center production environment (as defined in the Custom Application config). Upon successful login, you are redirected back to your local development server with a valid session.
If you were using the opt-in feature ENABLE_OIDC_FOR_DEVELOPMENT=true
, this is now the default behavior and you can remove the environment variable.
Recommended setup for EntryPoint
In the Custom Application <EntryPoint>
component we recommend to render the application content as children
of <ApplicationShell>
instead of the render
prop.
This allows the <ApplicationShell>
to pre-configure the application entry point routes. In addition to that, the entry point route is protected by the basic View
permission check. This means that a user without permissions of your Custom Application won't be able to access the Custom Application route.
import { ApplicationShell } from '@commercetools-frontend/application-shell';const loadMessages = async (locale) => {// ...};const AsyncApplicationRoutes = React.lazy(() => import('../../routes'));const EntryPoint = () => (<ApplicationShell environment={window.app} applicationMessages={loadMessages}><AsyncApplicationRoutes /></ApplicationShell>);export default EntryPoint;
Changes to the CLI
The mc-scripts
CLI has some breaking changes about the commands:
- In
mc-scripts
, thebuild
command additionally compiles theindex.html
by default.- Running the
compile-html
command by default should not be necessary anymore. However, you can pass--build-only
to thebuild
command to opt-out of the compilation step, in case you want to run it separately, for example to use the--transformer
.
- Running the
- Running the
compile-html
command by default does not print tostdout
the JSON string with the security headers. You can opt into the old behavior by passing the--print-security-headers
option. - The
--inline-csp
ofcompile-html
has been dropped, as it's now the built-in behavior. - The
dist
folder created by thebuild
command has been removed. Instead, thebuild
command writes the production bundles directly into thepublic
folder.
Better deployments support
With the new improvements in the developer tools, it's now even simpler to deploy a Custom Application to all the major hosting services. In fact, you can now take advantage of the GitHub integration with some of those hosting providers, without any extra effort around configuration.
Previously you would need to use the --transformer
option of the compile-html
command to configure the configuration file of the hosting provider.
Now most of the things are built-in and defined as defaults, removing the need to dynamically create a configuration file. As a result, configurations for the hosting provider can be defined statically, thus allowing to fully use the GitHub integration features.
Check out the deployment examples pages for more information.
Changes to Test Utils
The @commercetools-frontend/application-shell/test-utils
has the following breaking changes:
The
disableApolloMocks
option has been removed. By default, the Apollo mocks are deactivated. This is to encourage mocking via Mock Service Worker. To opt into the usage of Apollo mocks, you only need to pass themocks
property with a non-empty array. See Testing for more information.The
disableAutomaticEntryPointRoutes
option now defaults tofalse
. This means that when rendering the<ApplicationShell>
, you should not use therender
function but pass the application component usingchildren
.entry-point.jsJavaScriptconst EntryPoint = () => (<ApplicationShellenvironment={window.app}applicationMessages={loadMessages}><AsyncApplicationRoutes /></ApplicationShell>);The application
View
permission is automatically applied to theproject
object, based on theenvironment.entryPointUriPath
value. You can always override the permission values by explicitly assigningproject.allAppliedPermissions
.The deprecated
project.allAppliedMenuVisibilities
option has been removed.The deprecated
permissions
option has been removed. Useproject.allAppliedPermissions
instead.// Before{permissions: {canManageProducts: true;}}// After{project: {allAppliedPermissions: [{ name: 'canManageProducts', value: true }];}}You can also use the helper function
mapResourceAccessToAppliedPermissions
(recommended)import { mapResourceAccessToAppliedPermissions } from '@commercetools-frontend/application-shell/test-utils';{project: {allAppliedPermissions: mapResourceAccessToAppliedPermissions([PERMISSIONS.View])},}or the
denormalizePermissions
function.import { denormalizePermissions } from '@commercetools-frontend/application-shell/test-utils';{project: {allAppliedPermissions: denormalizePermissions({canManageProducts: true,});}}
To help defining the list of applied permissions, you can use the helper function mapResourceAccessToAppliedPermissions
or denormalizePermissions
.
Note that if you were testing your Custom Application with Cypress, you need to use the @commercetools-frontend/cypress
package to be able to use the cy.loginByOidc
command. See End-to-End tests for more information.