<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jordan Eisenburger</title>
    <description>The latest articles on DEV Community by Jordan Eisenburger (@jordaneisenburg).</description>
    <link>https://dev.to/jordaneisenburg</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F338878%2Fdfc9531a-635e-474d-964a-f8801fb279ad.png</url>
      <title>DEV Community: Jordan Eisenburger</title>
      <link>https://dev.to/jordaneisenburg</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jordaneisenburg"/>
    <language>en</language>
    <item>
      <title>Refetch active Apollo queries in PWA Studio on user action</title>
      <dc:creator>Jordan Eisenburger</dc:creator>
      <pubDate>Thu, 11 Feb 2021 13:39:33 +0000</pubDate>
      <link>https://dev.to/jordaneisenburg/refetch-active-apollo-queries-in-pwa-studio-on-user-action-fhf</link>
      <guid>https://dev.to/jordaneisenburg/refetch-active-apollo-queries-in-pwa-studio-on-user-action-fhf</guid>
      <description>&lt;p&gt;In some use cases you need to refetch your GraphQL queries on a user action. To do this you need to tell your &lt;code&gt;&amp;lt;query&amp;gt;&lt;/code&gt; component to refetch the data. Triggering this can be hard to do from a different part of your code base.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;As an example:&lt;/strong&gt;&lt;br&gt;
I have a B2B webshop. The customer is on the product page and can see regular/general prices. But when he logs in the product info/prices need to update to reflect his special info/prices.&lt;/p&gt;

&lt;p&gt;There is no easy way to do this besides either doing a page reload that will force reload the whole page and queries or use Apollo's &lt;code&gt;client.resetStore()&lt;/code&gt; but this will reset the whole store and refetch all active queries.&lt;/p&gt;

&lt;p&gt;To do this more surgical we can use something like this snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// refetchQueriesByName.js

const findQueries = (manager, names) =&amp;gt; {
    const matching = [];
    manager.queries.forEach(q =&amp;gt; {
        if (q.observableQuery &amp;amp;&amp;amp; names.includes(q.observableQuery.queryName)) {
            matching.push(q);
        }
    });
    return matching;
};

export const refetchQueriesByName = (names, client) =&amp;gt; {
    return Promise.all(
        findQueries(client.queryManager, names).map(q =&amp;gt;
            q.observableQuery.refetch(),
        ),
    );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Implementation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// packages/peregrine/lib/talons/SignIn/useSignIn.js

import { refetchQueriesByName } from 'PATH_TO/refetchQueriesByName';

    const handleSubmit = useCallback(
        async ({ email, password }) =&amp;gt; {
            setIsSigningIn(true);
            try {

                ...

                // Place somewhere after 'const destinationCartId = await retrieveCartId();'


                // These names are the actual names you declared in your graphql files
                await refetchQueriesByName(
                    [
                        'productDetail',
                        'relatedProducts',
                    ],
                    apolloClient
                ); 

                ...

})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>graphql</category>
    </item>
    <item>
      <title>Enhanced eCommerce in PWA Studio</title>
      <dc:creator>Jordan Eisenburger</dc:creator>
      <pubDate>Mon, 18 Jan 2021 21:24:20 +0000</pubDate>
      <link>https://dev.to/jordaneisenburg/enhanced-ecommerce-in-pwa-studio-1cjl</link>
      <guid>https://dev.to/jordaneisenburg/enhanced-ecommerce-in-pwa-studio-1cjl</guid>
      <description>&lt;p&gt;This blog post is mainly aimed at Magento agencies building a mono-repo around PWA Studio and having a need to make an easy yet extensible way to add Enhanced eCommerce.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that if you don't have a mono repo setup like PWA Studio you won't need the React Context&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding Google Tag Manager&lt;/li&gt;
&lt;li&gt;Creating a React Context&lt;/li&gt;
&lt;li&gt;Setting up a basic data layer file&lt;/li&gt;
&lt;li&gt;Implementing the data layer methods&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Adding Google Tag Manager
&lt;/h3&gt;

&lt;p&gt;Add the code below, make sure to add your own GTM code.&lt;br&gt;
I'd advice you to make the GTM code variable so you can connect to multiple containers based on your build/pipeline etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//template.html (the inside your storefront)
&amp;lt;script&amp;gt;
    dataLayer = [];
&amp;lt;/script&amp;gt;
&amp;lt;!-- Google Tag Manager --&amp;gt;
&amp;lt;script&amp;gt;
    (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
            new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
        j=d.createElement(s),dl=l!='dataLayer'?'&amp;amp;l='+l:'';j.async=true;j.src=
        'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
    })(window,document,'script','dataLayer','GTM-XXXXXX');
&amp;lt;/script&amp;gt;
&amp;lt;!-- End Google Tag Manager --&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating a React Context
&lt;/h3&gt;

&lt;p&gt;Since we are working inside a mono-repo we want to be able to customise what data we send to the data layer per customer that's build upon the mono-repo.&lt;/p&gt;

&lt;p&gt;So firstly locate the position where you'd normally would create context's inside your project.&lt;/p&gt;

&lt;p&gt;Add the following files:&lt;br&gt;
&lt;code&gt;context/dataLayer/index.js&lt;/code&gt;&lt;br&gt;
&lt;code&gt;context/dataLayer/dataLayer.js&lt;/code&gt;&lt;br&gt;
&lt;code&gt;context/dataLayer/data.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//context/dataLayer/index.js
export { DataLayerProvider, useDataLayerConfig } from './dataLayer';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//context/dataLayer/dataLayer.js

import React, { useContext } from 'react';
import { node, object } from 'prop-types';
import { merge } from 'lodash-es';
import { dataLayerConfig } from './data';

export const DataLayer = React.createContext(null);

const defaultDataLayer = dataLayerConfig;

export const DataLayerProvider = ({ children, additionalDataLayer = {} }) =&amp;gt; {
    return (
        &amp;lt;DataLayer.Provider
            value={merge({}, defaultDataLayer, additionalDataLayer)}
        &amp;gt;
            {children}
        &amp;lt;/DataLayer.Provider&amp;gt;
    );
};

export const useDataLayerConfig = () =&amp;gt; useContext(DataLayer);

DataLayerProvider.propTypes = {
    children: node.isRequired,
    query: object,
    additionalDataLayer: object,
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//context/dataLayer/data.js
export const dataLayerConfig = {
    reset: {
        product: () =&amp;gt; ({
            ecommerce: undefined,
            items: undefined,
        }),
        category: () =&amp;gt; ({
            ecommerce: undefined,
            items: undefined,
        }),
    },
    product: data =&amp;gt; ({
        event: 'virtualPageview',
        pagePath: window.location.href,
        pageTitle: `${data.name} - ${STORE_NAME}`,
        pageType: 'product',
        items: [
            {
                id: data.sku,
            },
        ],
        ecommerce: {
            detail: {
                products: [
                    {
                        name: data.name,
                        id: data.sku,
                    },
                ],
            },
        },
    }),
    cms: data =&amp;gt; ({
        event: 'virtualPageview',
        pagePath: window.location.href,
        pageTitle: `${data.title} - ${STORE_NAME}`,
        pageType: 'cms',
    }),
    category: data =&amp;gt; ({
        event: 'virtualPageview',
        pagePath: window.location.href,
        pageTitle: `${data.category.name} - ${STORE_NAME}`,
        pageType: 'category',
    }),
    removeFromCart: data =&amp;gt; ({
        event: 'removeFromCart',
        ecommerce: {
            remove: {
                products: [
                    {
                        name: data.product.name,
                        id: data.product.sku,
                        quantity: data.quantity,
                    },
                ],
            },
        },
    }),
    addToCart: data =&amp;gt; ({
        event: 'addToCart',
        items: [
            {
                id: data.sku,
            },
        ],
        ecommerce: {
            add: {
                products: [
                    {
                        name: data.name,
                        id: data.sku,
                        quantity: data.quantity,
                    },
                ],
            },
        },
    }),
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note that this a really small example file, you should add more methods like submitOrder, checkoutSuccess, checkout, notFound etc etc&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Make sure to import the Context into the storefront and add it to the provider tree.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//index.js (the on in your storefront)
&amp;lt;AppContextProvider&amp;gt;
  &amp;lt;DataLayerProvider&amp;gt;
    ...
  &amp;lt;/DataLayerProvider&amp;gt;
&amp;lt;/AppContextProvider&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementing the data layer methods
&lt;/h3&gt;

&lt;p&gt;So we've set up the basic of this solution &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>magento</category>
      <category>analytics</category>
    </item>
    <item>
      <title>How to setup Sirv for PWA Studio</title>
      <dc:creator>Jordan Eisenburger</dc:creator>
      <pubDate>Wed, 12 Aug 2020 15:27:27 +0000</pubDate>
      <link>https://dev.to/jordaneisenburg/how-to-setup-sirv-for-pwa-studio-3jma</link>
      <guid>https://dev.to/jordaneisenburg/how-to-setup-sirv-for-pwa-studio-3jma</guid>
      <description>&lt;p&gt;This blog will show you the steps to setup Sirv with a PWA Studio 7.0.0 environment. This post expects you to already have an Sirv account ready.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Configuring Magento
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Go to your magento backend and navigate to "Store -&amp;gt; General -&amp;gt; web"&lt;/li&gt;
&lt;li&gt;Change both "Base URL for User Media Files" and "Secure Base URL for User Media Files" to use your Sirv media url. For example: &lt;a href="https://static.your-webshops.com/media/"&gt;https://static.your-webshops.com/media/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Step 2: Change your &lt;code&gt;.env&lt;/code&gt; file
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Go to your &lt;code&gt;.env&lt;/code&gt; file located in the root of your pwa studio project&lt;/li&gt;
&lt;li&gt;Change &lt;code&gt;IMAGE_OPTIMIZING_ORIGIN&lt;/code&gt; to &lt;code&gt;IMAGE_OPTIMIZING_ORIGIN=backend&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;This will tell PWA Studio that we are going to use another image optimisation tool instead of the onboard image  optimisation&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Step 3: Prepare the makeUrl file
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Open &lt;code&gt;@magento/venia-ui/lib/util/makeUrl.js&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;We need to export &lt;code&gt;useBackendForImgs&lt;/code&gt; change it so we get the following: &lt;code&gt;export const useBackendForImgs = imageOptimizingOrigin === 'backend';&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Find the following code block:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const params = new URLSearchParams(baseURL.search);
    params.set('auto', 'webp'); // Use the webp format if available

    const imageFileType = getFileType(baseURL);
    if (imageFileType === 'png') {
        params.set('format', 'png'); // use png if webp is not available
    } else {
        params.set('format', 'pjpg'); // Use progressive JPG if webp is not available
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And change it like shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const params = new URLSearchParams(baseURL.search);

    if (!useBackendForImgs) {
        params.set('auto', 'webp'); // Use the webp format if available

        const imageFileType = getFileType(baseURL);
        if (imageFileType === 'png') {
            params.set('format', 'png'); // use png if webp is not available
        } else {
            params.set('format', 'pjpg'); // Use progressive JPG if webp is not available
        }
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Step 4: Change the url params to be compliant with Sirv's format
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Open &lt;code&gt;@magento/venia-ui/lib/drivers/index.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Change &lt;code&gt;export { default as resourceUrl } from '../util/makeUrl';&lt;/code&gt; to &lt;code&gt;export { default as resourceUrl, useBackendForImgs } from '../util/makeUrl';&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;@magento/venia-ui/lib/util/images.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;on line &lt;code&gt;1&lt;/code&gt; import &lt;code&gt;useBackendForImgs&lt;/code&gt; like so: &lt;code&gt;import { resourceUrl, useBackendForImgs } from '@magento/venia-drivers';&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Replace the &lt;code&gt;generateUrl&lt;/code&gt; function with the code below:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const generateUrl = (imageURL, mediaBase) =&amp;gt; (width, height) =&amp;gt; {
    if (useBackendForImgs) {
        const regex = /cache\/.+?(?=\/)\//;
        const imageURLWithoutCacheKey = imageURL.replace(regex, '');
        return resourceUrl(imageURLWithoutCacheKey, {
            type: mediaBase,
            'scale.width': width,
            'scale.height': height,
        });
    }

    return resourceUrl(imageURL, {
        type: mediaBase,
        width,
        height,
        fit: 'cover',
    });
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NOTE: if the imageUrl doesn't has the cache key included you can remove the regex part. Also the regex is a dirty fix because the urls should come back from the API without the cache key. We only care about originals.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  That's it you've done it!
&lt;/h2&gt;

&lt;p&gt;Well not quite yet :( if you open up chrome dev tools and open the 'Application -&amp;gt; Cache Storage' you should see (must have SW enabled) an entry called 'catalog - &lt;a href="https://yourwebshop.com"&gt;https://yourwebshop.com&lt;/a&gt;' this holds all catalog images.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Response-Type&lt;/code&gt; for images will probably say &lt;code&gt;opaque&lt;/code&gt; this will result in an extremely large sw storage size most likely it shows an error in the chrome console saying something like "the quota is exceeded". When the &lt;code&gt;Response-Type&lt;/code&gt; is &lt;code&gt;opaque&lt;/code&gt; it will reserve 7MB per image.&lt;/p&gt;

&lt;p&gt;To fix this problem we need to make the following changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;crossorigin="anonymous"&lt;/code&gt; to all custom &lt;code&gt;img&lt;/code&gt; elements like so: &lt;code&gt;&amp;lt;img crossorigin="anonymous" src="blabla" /&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;src/ServiceWorker/Utilities/imageCacheHandler.js&lt;/code&gt; and change line &lt;code&gt;98&lt;/code&gt; from &lt;code&gt;mode: 'no-cors'&lt;/code&gt; to &lt;code&gt;mode: 'anonymous'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Open &lt;code&gt;@magento/venia-ui/lib/components/Image/image.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add the prop &lt;code&gt;crossOrigin="anonymous"&lt;/code&gt; to the &lt;code&gt;&amp;lt;SimpleImage&lt;/code&gt; and &lt;code&gt;&amp;lt;ResourceImage&lt;/code&gt; component.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Congratulations! You now have Sirv working with PWA studio
&lt;/h2&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Feasibility report for implementing PWA Studio v7.0.0</title>
      <dc:creator>Jordan Eisenburger</dc:creator>
      <pubDate>Wed, 05 Aug 2020 14:52:00 +0000</pubDate>
      <link>https://dev.to/jordaneisenburg/feasibility-report-for-implementing-pwa-studio-v7-0-0-135g</link>
      <guid>https://dev.to/jordaneisenburg/feasibility-report-for-implementing-pwa-studio-v7-0-0-135g</guid>
      <description>&lt;p&gt;Before you start working with Studio it's important to know if you are a one-time implementer or an agency hoping to do multiple projects with Studio. As far as I see it there are two ways of implementing Studio: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You use the scaffolding command @magento/create-pwa &lt;/li&gt;
&lt;li&gt;You create a mono-repo that depends on the packages from Studio that serves as your core product&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A merchant with in-house developers
&lt;/h2&gt;

&lt;p&gt;When you are a merchant and want to make the transition to PWA Studio and you don’t have a partner agency. It makes a lot of sense for your developers (in-house or freelance) to use the scaffolding tool since there’s probably only one webshop going to be built upon the system this route gives you a flying start into your project.&lt;/p&gt;

&lt;h4&gt;
  
  
  Feature support:
&lt;/h4&gt;

&lt;p&gt;Before start development examine your current webshops and create a list of features that you actually use (not the once you have but never use) this will keep the PWA lightweight, reduce development time and thus keep costs lower. &lt;/p&gt;

&lt;h4&gt;
  
  
  Development team:
&lt;/h4&gt;

&lt;p&gt;Studio is fully API driven which means that besides a front-end developer with Javascript/react experience you also need a back-end developer preferably with GraphQL experience to create new endpoints that can interpret by the PWA&lt;/p&gt;

&lt;h4&gt;
  
  
  3rth party module support:
&lt;/h4&gt;

&lt;p&gt;If your curated list of features include a lot of 3rth party modules then most likely you are going to have to put development time into adding API support for these modules. But before you do so check their websites, with PWA/headless becoming more of a household name 3rth party extension developers slowly start adding API support. &lt;/p&gt;

&lt;p&gt;Note that at this point in time there are no 3rth party extensions that I’m aware of that deliver both API Support and Studio compatible front-end components. This means that you are going to create those yourself. Let’s say you make use of a module that has 8 functionalities but you only really use 2, just create a frontend that supports just those two. This will keep the costs lower and functionalities tailored to your webshop.&lt;/p&gt;




&lt;h2&gt;
  
  
  An Agency
&lt;/h2&gt;

&lt;p&gt;When you are an agency like Experius and are planning to implement multiple projects for different customers you’d want to go with the mono-repo approach. This way gives you a lot of freedom in terms of what packages you use from Studio but also a solid base product that can easily be upgraded to a newer version of Studio to keep all you customers up-to-date with the latest development by Magento.&lt;/p&gt;

&lt;h4&gt;
  
  
  Feature support:
&lt;/h4&gt;

&lt;p&gt;When you start working on your first project make sure to backport all functionalities to your mono-repo. For example when you need to add bundled product support for your customer build it in your mono-repo as generic as possible and tweak it to the customers needs in their project that’s built with the mono-repo. When you start doing this for all features and new projects your mono-repo will grow really fast and before you know it you will have a full repo of packages ready to rapidly develop any project&lt;/p&gt;

&lt;h4&gt;
  
  
  Development team:
&lt;/h4&gt;

&lt;p&gt;Studio is fully API driven which means that besides a front-end developer with Javascript/react experience you also need a back-end developer preferably with GraphQL/Rest experience to create new endpoints that can be interpreted by the PWA.&lt;/p&gt;

&lt;h4&gt;
  
  
  3rth party module support:
&lt;/h4&gt;

&lt;p&gt;This is basically the same workflow as “Feature support” above.&lt;/p&gt;




&lt;h5&gt;
  
  
  Pain points:
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Would love to see more feature / bugfix releases instead of only major version releases.&lt;/li&gt;
&lt;li&gt;Not all basic shop features are implemented yet by the Studio team.&lt;/li&gt;
&lt;li&gt;At the moment you need to do a lot of overwriting instead of a possibility to extend files/functionalities, in 7.0.0 the new extensibility framework made it's debut. This is a huge improvement but the PWA Studio core still needs to be prepared for overwrites.&lt;/li&gt;
&lt;li&gt;No full SEO support so you need to use something like SeoSnap.io like we do over at Experius.&lt;/li&gt;
&lt;li&gt;If you are an agency with “traditional” Magento developers (little to no reactjs/javascript) you will need to put time into learning.&lt;/li&gt;
&lt;li&gt;You need to make sure your PSP supports headless environments, if not they will have to add support for it. &lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Wins:
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;If done right you need less development time in the long run.&lt;/li&gt;
&lt;li&gt;An awesome community / Studio team.&lt;/li&gt;
&lt;li&gt;Lots of development joy for your developers.&lt;/li&gt;
&lt;li&gt;Easy to implement new techniques from the always evolving front-end space.&lt;/li&gt;
&lt;li&gt;A future proof webshop&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Recommendations:
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Start simple, don't try to build everything before launch go with the essentials first.&lt;/li&gt;
&lt;li&gt;Make sure to have you components/utilities covered with unit tests&lt;/li&gt;
&lt;li&gt;Setup a pipeline (GitHub, Bitbucket etc) and run E2E tests in the pipeline before your new code reaches an environment. We use Cypress.io over at Experius&lt;/li&gt;
&lt;li&gt;Join the #pwa slack channel&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Final note:
&lt;/h4&gt;

&lt;p&gt;Having created 3 pwa studio projects that run in production and more projects in the making I’ve seen both the pwa community and PWA Studio as a product make major jumps forward. My main tip would be: Ship, learn and then iterate&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
