Menu
Menu Sheet Overlay
Search
Search Sheet

Shared Code Between PWA and AMP

    The Mobify Platform’s architecture encourages developers to share code between a PWA project and an AMP project. Once a PWA project is complete, this code sharing drastically reduces the effort required to also deliver an AMP-compatible ecommerce experience.

    We will cover what part may or may not be affected by code sharing. Anything that is shared between the PWA and AMP requires some effort to ensure that it doesn’t break your project when you make a change. The effort can be testing your project or checking the page. Not every part of your project is being shared because the PWA and AMP both have different technical requirements and limitations.

    Contents

    We’ve organized this document around the following parts of your codebase:

    Shared Code Between PWA and AMP

    Constants #

    You don’t have to redefine JavaScript constants in your AMP code if you’ve already defined them in your PWA code. The PWA architecture features a single file for defining constants, making them easy to import into your AMP code.

    Here’s an example that shows how to import the ITEMS_PER_PAGE constant:

    // Product List Partial
    // file: project/amp/app/containers/product-list/partials/product-list-contents.jsx
    
    import {ITEMS_PER_PAGE} from 'web/app/containers/product-list/constants'
    

    Keeping all your constants in one file is much easier than duplicating them in multiple files and having to keep them in sync.

    Containers #

    The PWA and AMP should have its own containers, it should not be shared. They both have different technical requirements and limitations, it should be treated as two different projects.

    Data Integration #

    Since both of the PWA and AMP experiences share the same ecommerce data, you’ll save a lot of time by using the same connectors, reducers and Redux Store.

    // Using a connector from the PWA in AMP
    // file: project/amp/app/data-integration/connectors/merlins-connector.js
    
    import {Connector} from 'web/app/connectors/_merlins-connector'
    
    // Share the reducers from the PWA in AMP
    // file: amp/app/data-integration/connectedStore.js
    
    import footerReducer from 'web/app/containers/footer/reducer'
    import homeReducer from 'web/app/containers/home/reducer'
    import navigationReducer from 'web/app/modals/navigation/reducer'
    import productListReducer from 'web/app/containers/product-list/reducer'
    

    Global Styles #

    There are certain styles from your PWA project that can be easily imported into your AMP project without affecting any AMP-specific styling rules. These styles are defined in the following files:

    For example, here’s how to import the utility classes:

    // file: project/amp/app/styles/_utilities.scss
    
    @import '~web/app/styles/utilities'; // “~”, the tilde character tells the Webpack that this is not a relative import
    

    The next example demonstrates how to share SCSS variables. Sharing these variables makes it easier to maintain the same look and feel across the PWA and AMP experiences.

    // file: project/amp/app/styles/_variables.scss
    
    @import '~web/app/styles/variables';
    

    Whenever you make a change to any shared styles, be sure to test both the PWA and AMP experiences to verify that the styles work as expected in both.

    Note that there are CSS size limitations in AMP, make sure you are being picky about what to import from the PWA into your AMP. It’s important to be aware of your total CSS file size, whether styles in shared CSS files are being used or not, and ensuring you're using valid AMP CSS when you are importing styles from the PWA into AMP.

    Selectors #

    Selectors can be shared between the PWA and AMP, in this example, we import the product list selectors:

    // file: project/amp/app/containers/product-list/partials/product-list-contents.jsx
    
    import * as selectors from 'web/app/containers/product-list/selectors'
    

    Static Assets #

    Static assets are not shared between the PWA and AMP, which have their own static folders. Static files are not shared because the PWA and AMP have their own static buckets in the cloud. The PWA and AMP use a different utility function that creates a path to a static folder.

    On AMP it uses staticURL utility function, for example,

    <Img src={staticURL('svg/logo.svg')} width="67" height="28" layout="fixed" alt=”Logo” />
    // https://cdn.mobify.net/amp/v0/df7e4f8a-7af3-4522-b2af-e384e387027e/svg/logo.svg
    

    On PWA, it uses getAssetUrl utility function, for example,

    <Image src={getAssetUrl(`svg/logo.svg`)} alt=”Logo” />
    // https://cdn.mobify.com/sites/progressive-web-scaffold/production/static/svg/logo.svg
    

    UI components #

    Components should not be shared between the PWA and AMP, even though many of them share the same name and have similar functionality. The reason why the PWA and AMP have their own set of components is because both have different requirements and limitations. AMP is built with its own technology, and components need to be compatible with that technology. Also, AMP has built-in components that can be built with AMP components. For example, the AMP Sheet component is built with the amp-sidebar component. PWA components live in /web/app/components and AMP components live in /amp/app/components.

    Although UI components are not shared, we recommend that the components used in both PWA and AMP should be kept in sync. For example, if you are making changes to a PWA component, you should make sure that the AMP version of it gets the same change. It’s important for components to be kept in sync because if they drift apart it will be harder to find and address bugs.

    Utility Functions #

    Utility functions can be shared across PWA and AMP. The following code snippet is an example of using a PWA utility function in the context of AMP.

    // file: project/amp/app/containers/product-list/partials/product-list-contents.jsx
    
    import {validatePageNumber} from ''web/app/utils/utils'