What you’ll learn
  • how to upgrade Webiny from 5.6.0 to 5.7.0
Before continuing, make sure to take the necessary precautions, listed in the Overview section.
Make sure to check out the 5.7.0 changelog to get familiar with all the changes introduced in this release.

Upgrade Webiny Packages
anchor

The first step is to upgrade all @webiny/* packages, which can be done by running the following command in the root of your project:

# Execute in your project root.
yarn up "@webiny/*@5.7.0"

Once the packages upgrade has finished, running the yarn webiny --version command in your terminal should return 5.7.0.

Upgrade Lambda Handlers
anchor

In order to benefit from the new API Error Overlay feature, we need to add some tweaks to the configuration of our Lambda handlers.

graphql Lambda Handler
anchor

In your api/code/graphql/src/index.ts file, add a debug variable and modify the call to createHandler to use a configuration object:

api/code/graphql/src/index.ts
// your existing import statements

const debug = process.env.DEBUG === "true";

export const handler = createHandler({
  plugins: [
    // your existing plugins
  ],
  http: { debug }
});

Also change the graphqlPlugins({ debug: process.env.DEBUG }) to graphqlPlugins({ debug }), as we’re now very strict about the type of debug parameter (it now has to be a boolean). That’s why we explicitly define that variable once, and reuse it where needed.

As you can see, we now use a configuration object to explicitly pass plugins and other parameters required by the Lambda handler factory package. The http: { debug } will be passed all the way to the internal @webiny/handler-http external link package which will handle the errors for us.

NOT SURE WHAT TO DO?

If unsure what the final result should look like, please see the original file external link for a complete example.

headlessCMS Lambda Handler
anchor

The same change applies to headlessCMS Lambda. In your api/code/headlessCMS/src/index.ts file, add a debug variable and modify the call to createHandler to use a configuration object:

api/code/headlessCMS/src/index.ts
// your existing import statements

const debug = process.env.DEBUG === "true";

export const handler = createHandler({
  plugins: [
    // your existing plugins
  ],
  http: { debug }
});
NOT SURE WHAT TO DO?

If unsure what the final result should look like, please see the original file external link for a complete example.

Upgrade React Applications
anchor

Upgrade admin Application
anchor

Open your apps/admin/code/src/components/apolloClient.ts file and replace everything with the following:

apps/admin/code/src/components/apolloClient.ts
import ApolloClient from "apollo-client";
import { ApolloLink } from "apollo-link";
import { BatchHttpLink } from "apollo-link-batch-http";
import { InMemoryCache } from "apollo-cache-inmemory";
import { plugins } from "@webiny/plugins";
import { ApolloDynamicLink } from "@webiny/app/plugins/ApolloDynamicLink";
import { CacheGetObjectIdPlugin } from "@webiny/app/types";

export const createApolloClient = ({ uri }) => {
  return new ApolloClient({
    link: ApolloLink.from([
      /**
       * This will process links from plugins on every request
       */
      new ApolloDynamicLink(),
      /**
       * This batches requests made to the API to pack multiple requests into a single HTTP request.
       */
      new BatchHttpLink({ uri })
    ]),
    cache: new InMemoryCache({
      addTypename: true,
      dataIdFromObject: obj => {
        /**
         * Since every data type coming from API can have a different data structure,
         * we cannot rely on having an `id` field.
         */
        const getters = plugins.byType<CacheGetObjectIdPlugin>("cache-get-object-id");
        for (let i = 0; i < getters.length; i++) {
          const id = getters[i].getObjectId(obj);
          if (typeof id !== "undefined") {
            return id;
          }
        }

        /**
         * As a fallback, try getting object's `id`.
         */
        return obj.id || null;
      }
    })
  });
};

The important parts are highlighted in the code. We replaced all custom Apollo links with a single ApolloDynamicLink to handle everything via plugins.

Now we need to register those links we just removed using plugins.

Create a file apps/admin/code/src/plugins/apolloLinks.ts and paste the following into it:

apps/admin/code/src/plugins/apolloLinks.ts
import { ConsoleLinkPlugin } from "@webiny/app/plugins/ConsoleLinkPlugin";
import { NetworkErrorLinkPlugin } from "@webiny/app/plugins/NetworkErrorLinkPlugin";
import { OmitTypenameLinkPlugin } from "@webiny/app/plugins/OmitTypenameLinkPlugin";

export default [
  /**
   * This link removes `__typename` from the variables being sent to the API.
   */
  new OmitTypenameLinkPlugin(),
  /**
   * This link checks for presence of `extensions.console` in the response and logs all items to browser console.
   */
  new ConsoleLinkPlugin(),
  /**
   * This plugin creates an ApolloLink that checks for `NetworkError` and shows an ErrorOverlay in the browser.
   */
  new NetworkErrorLinkPlugin()
];

Now we just need to import this new file to register them with the application. Open apps/admin/code/src/plugins/index.ts, import the new plugins, and register them:

apps/admin/code/src/plugins/index.ts
import { plugins } from "@webiny/plugins";
import { WebinyInitPlugin } from "@webiny/app/types";
import welcomeScreenPlugins from "@webiny/app-plugin-admin-welcome-screen";
import routeNotFound from "./routeNotFound";
import basePlugins from "./base";
import apolloLinkPlugins from "./apolloLinks";
import adminPlugins from "./admin";
import i18nPlugins from "./i18n";
import i18nContentPlugins from "./i18nContent";
import securityPlugins from "./security";
import pageBuilderPlugins from "./pageBuilder";
import formBuilderPlugins from "./formBuilder";
import headlessCmsPlugins from "./headlessCms";
import theme from "theme";

plugins.register([
  /**
   * Base app plugins (files, images).
   */
  basePlugins,
  /**
   * ApolloClient link plugins.
   */
  apolloLinkPlugins,
  /**
   * Complete admin app UI.
   */
  adminPlugins,
  /**
   * Renders a welcome screen with useful links at "/".
   */
  welcomeScreenPlugins(),
  /**
   * Handles location paths that don't have a corresponding route.
   */
  routeNotFound,
  /**
   * Internationalization app.
   */
  i18nPlugins,
  /**
   * Enables storing content (pages, forms, content, ...) in multiple locales.
   */
  i18nContentPlugins,
  /**
   * Security app and authentication plugins.
   */
  securityPlugins,
  /**
   * Page Builder app.
   */
  pageBuilderPlugins,
  /**
   * Form Builder app.
   */
  formBuilderPlugins,
  /**
   * Headless CMS app.
   */
  headlessCmsPlugins,
  /**
   * App theme controls page builder and form builder layouts, styles, etc.
   */
  theme()
]);

plugins.byType<WebinyInitPlugin>("webiny-init").forEach(plugin => plugin.init());

Upgrade website Application
anchor

Open apps/website/code/src/components/apolloClient.ts and replace everything with the following code:

apps/website/code/src/components/apolloClient.ts
import ApolloClient from "apollo-client";
import { ApolloLink } from "apollo-link";
import { BatchHttpLink } from "apollo-link-batch-http";
import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloDynamicLink } from "@webiny/app/plugins/ApolloDynamicLink";

export const createApolloClient = () => {
  const isProduction = process.env.NODE_ENV === "production";

  const cache = new InMemoryCache({
    addTypename: true,
    dataIdFromObject: obj => obj.id || null
  });

  if (isProduction && process.env.REACT_APP_ENV === "browser") {
    // Production build of this app will be rendered using SSR so we need to restore cache from pre-rendered state.
    // @ts-ignore
    cache.restore(window.__APOLLO_STATE__);
  }

  // @ts-ignore
  cache.restore("__APOLLO_STATE__" in window ? window.__APOLLO_STATE__ : {});

  const uri = process.env.REACT_APP_GRAPHQL_API_URL;
  const link = ApolloLink.from([new ApolloDynamicLink(), new BatchHttpLink({ uri })]);

  // @ts-ignore
  window.getApolloState = () => {
    // @ts-ignore
    return cache.data.data;
  };

  return new ApolloClient({ link, cache });
};

Lastly, open apps/website/code/src/plugins/apolloLinks.ts and replace everything with the following code:

apps/website/code/src/plugins/apolloLinks.ts
import { OmitTypenameLinkPlugin } from "@webiny/app/plugins/OmitTypenameLinkPlugin";
import { LocaleHeaderLinkPlugin } from "@webiny/app/plugins/LocaleHeaderLinkPlugin";
import { TenantHeaderLinkPlugin } from "@webiny/app/plugins/TenantHeaderLinkPlugin";

export default () => [
  /**
   * This link removes `__typename` from the variables being sent to the API.
   */
  new OmitTypenameLinkPlugin(),
  /**
   * Append `x-tenant` header from URL query (necessary for prerendering service).
   */
  new TenantHeaderLinkPlugin(),
  /**
   * Append `x-i18n-locale` header from URL query (necessary for prerendering service).
   */
  new LocaleHeaderLinkPlugin()
];

Redeploy!
anchor

Now you’re ready to redeploy your API and apps. By now, you’re most likely familiar with the deployment process, but if you need a refresher, visit our Deploy Your Project guide for everything related to deployments.