Teaser for Getting started with Magento PWA Studio

Getting started with Magento PWA Studio

6 min read

Edit post on GitHub

This blog post covers two areas. The first part is more from the business side of view. In the second part, we will cover how you can build a solid project with PWA Studio.

Is PWA the right technology for my requirements

As with all software projects, it should start with the why. What can a customer or a developer expect from a progressive web app (PWA) Project?

In my experience, when new technology appears, stakeholders do not ask about any added business values or requirements first. But often jump on the hype train without a good reason. In my opinion, a better approach could be using Why, How, What (golden circle) before starting a Project with headless technologies. The why should be very customer-focused, but also do not forget about your organization strategies?

Why would we like to build the next project as a (PWA)?

  • We expect a better customer experience for our smartphones users.
  • A seamlessly integrated configurator could also contribute to our customer experience goal.

How PWA improves the customer experience?

  • Offline support (to handle short interruptions)

What is the advantage of using this new technology?

  • Split between business logic and user interface
    • Better for writing tests and view cloud change with business logic
  • Your Frontend Team doesn't need to know about Magento frontend stack high entry barrier

What is the technical trade-off in building a Headless frontend?

  • A spilt between Backend (PHP) and Frontend (React, GraphQL)
  • You need to build a new feature in the backend and frontend

What are the target group of my PWA Project?

I think that headless is the future, especially for large e-commerce projects. Is the separation of frontend and backend beneficial to tame the complexity? A good Content Commerce strategy based on Adobe Experience Manager get more and more requested nowadays. In the future, I expected more seamless integration from all Adobe products in a headless storefront. That was one of the reasons why I got so involved with PWA. Now is an excellent time to gain the first experience in real projects with the new PWA technology.

How to create an own PWA Studio Theme

After some significant technical and Bussines strategies meetings, you decided to start building a storefront based on PWAStudio. I know there many more solutions for Magento (Adobe Commerce) to build a Storefront.In my experience select, a product not developed by Adobe brings your Project, not an ideal situation in terms of support and maintainability. What I like significantly about PWA Studio is the extensibility of APIs.

They are not so common in the React environment but are extremely helpful in developing your own storefront experience. Before starting a project, you should ensure your development team knows about React, HTML, CSS, Webpack. They are a used foundation.

Summary Blog post: https://marcin-kwiatkowski.com/how-to-extend-pwa-studio-with-new-features

Create a PWA Theme with Scaffolding

In this tutorial, we are going to extend the Main and create our TopBar component as the first element to our site.

In my experience, the Project scaffolding command developed by Adobe is an excellent way to start a project. Early adopters of the PWA Studio project forked, and the Core Team recommends not using this practice. With scaffolding, we should have the opportunity to build our own PWA Theme on top of Magento 2. The complete documentation of https://magento.github.io/pwa-studio/pwa-buildpack/scaffolding/

But it would help if you had some tweaks to get better maintainability.

Command to create a new Project:

yarn create @magento/pwa

It should look like:

If you work on a project with only the local-intercept.js, this file gets very fast confusing. I create a yarn extension that you install and get a better maintainable project. It allows you to .targetables.js in any competent which help to split the huge local-intercept.js in a file per component also it allows css overwrites and extension.

yarn add @larsroettig/component-targetables

Change your Project local-intercept.js file to:

const {
  componentTargetablesDefinitions,
} = require('@larsroettig/component-targetables');

function localIntercept(targets) {
  const { Targetables } = require('@magento/pwa-buildpack');
  const targetables = Targetables.using(targets);

  const extendLocalIntercept = new ExtendLocalIntercept(targetables);
  extendLocalIntercept.allowCustomTargetables();
  extendLocalIntercept.allowCssOverwrites();
}

Lets add a FreeGift before the header

import React from 'react';
import { useStyle } from '@magento/venia-ui/lib/classify';
import { FormattedMessage, useIntl } from 'react-intl';
import { BrowserPersistence } from '@magento/peregrine/lib/util';

import defaultClasses from './freeGift.css';
const storage = new BrowserPersistence();

const FreeGift = props => {
    const classes = useStyle(defaultClasses, props.classes);
    const { locale } = useIntl();

    const value = 20; // schould be fetch via graphql

    // fetchs the current currency from storage price compont
    const currencyCode = storage.getItem('store_view_currency') || 'USD';

    // sample to format a number price comp cloud be used here instad
    const amount = new Intl.NumberFormat(locale, {
        style: 'currency',
        currency: currencyCode
    }).format(value);

    return (
        <div className={classes.root}>
            <span>
                <FormattedMessage
                    id="freeGift" // Description should be a string literal
                    defaultMessage="Free Gift if you order for more then <b>{amount}</b>" // amount should be a string literal
                    values={{
                        amount,
                        // replace <b> tag via span with blod styling
                        b: chunks => (
                            <span className={classes.msg}>{chunks}</span>
                        )
                    }}
                />
            </span>
        </div>
    );
};

export default FreeGift;
.root {
    background-color: #baa683;
    text-align: center;
    padding: 1rem 0;
    color: rgb(var(--venia-global-color-gray-50));
}

.msg{
    font-weight: var(--venia-global-fontWeight-bold);
}

In our case we required to target node_modules/@magento/venia-ui/lib/components/Main/main.js todo that we need to create file under src/components/Main/main.targetables.js

/**
 * @param {MainComponent} MainComponent
 * @see @magento/venia-ui/lib/components/Main/main.js
 */
const interceptComponent = MainComponent => {
    // Adds the import to our main component
    MainComponent.addImport(
        "FreeGift from 'src/custom/components/FreeGift/freeGift.js'"
    );
    // Add our FreeGift component before <Header />
    MainComponent.insertBeforeJSX('Header', '<FreeGift />');
};

exports.interceptComponent = interceptComponent;

The Result in the core after transform

import FreeGift from 'src/custom/components/FreeGift/freeGift.js'

const Main = props => {
    const { children, isMasked } = props;
    const classes = useStyle(defaultClasses, props.classes);

    const rootClass = isMasked ? classes.root_masked : classes.root;
    const pageClass = isMasked ? classes.page_masked : classes.page;

    useScrollLock(isMasked);

    return (
        <main className={rootClass}>
            <FreeGiftMessage />
            <Header />
            <div className={pageClass}>{children}</div>
            <Footer />
        </main>
    );
};

If you learn more about the library pls visted the documentation.

Tips and Tricks

SEO

For JavaScript applications, it essential to use Server-Side Rendering (SSR). The benefit of using SSR is the website content can crawl from crawlers that don't execute JavaScript code. I recommend using tools like prerender.io or seosnap.io. When you use SSR to mind those errors, the request still can returns a 200 status code. You don't want these to cached by Rendertron or Seosnap your need to set <meta name="render:status_code" content="404" /> at the appropriate places.

Very nice blog post over Server-Side vs Client-Side Rendering and Changing SEO Practices.

Edit post on GitHub