DND Magento PWA Studio x Magento Cloud
by Florian, Magento Technical Officer at Agence Dn’D

The first steps can be found in PWA Studio documentation, you can follow each of them up to finding the correct UPWARD path value. Unfortunately, if you follow this documentation, you have to build the storefront on your local and push the sources on the repository which is against the one way coupling specified here. However, there is no possibility to decouple deployment as we’re facing the problem that we have only one environment given by Magento Cloud.

Create Magento Cloud Variables

You have two ways to create variables in Magento Cloud :

  • From the UI while clicking on the settings button,
  • From the command line with the Magento Cloud cli.

There are two kinds of variables, the project variables (which will interest us in our case) and the environment variables. The main difference between these two variables is that the project one can be used in the build hook (that’s why it will interest us).

Create two variables on the project level and don’t forget to tick (or specify as argument if you use clithat you want them visible during the build :

  • PWA_BRANCH => to map your branch on your PWA Studio repository
  • MAGENTO_BACKEND_URL => the url of your Magento

Give those variables a default value and then create those variables on each environment with the desired value (e.g. staging for your PWA_BRANCH on your staging environment). You can, if you want, create any variables that you want. If you print the variables for an environment, you must have this :

Variables on the project MyMcProject (mcdnd2021), environment staging:
+-----------------------------------------+-------------+-----------------------------------------------+---------+
| Name                                    | Level       | Value                                         | Enabled |
+-----------------------------------------+-------------+-----------------------------------------------+---------+
### VALUES FROM PROJECT LEVEL ###
| PWA_BRANCH                              | project     | integration                                   |         |
| MAGENTO_BACKEND_URL                     | project     | https://mcstaging.my-beautiful-website.com/   |         |
### VALUES FROM ENVIRONMENT LEVEL ###
| MAGENTO_BACKEND_URL                     | environment | https://mcstaging.my-beautiful-website.com/   | true    |
| PWA_BRANCH                              | environment | staging                                       | true    |
+-----------------------------------------+-------------+-----------------------------------------------+---------+

Build PWA Studio

There are three hooks available on Magento Cloud :

  • Build, which is the one that we’ll use in our case because it will allow us to clone our PWA Studio in our sources. At this moment, there are no services such as MySQL accessible.
  • Deploy, which is running after the moment that every container is up but not yet solicited. In this phase, Magento is down during the setup upgrade command execution.
  • Post-deploy, which will allow you to add some requests on your application like warming the cache.

Update the .magento.app.yml

Hooks can be modified in the .magento.app.yml present at the root of your Magento. In this file, you’ll find a node named hooks.

We decided to put everything in bash file to make it more lisible, here is the content of our hooks node :

# We run build hooks before your application has been packaged.
# Set permission & execute bash file
build: |
set -e
chmod u+x .hooks/bin/build.sh && ./.hooks/bin/build.sh
# We run deploy hook after your application has been deployed and started.
deploy: |
php ./vendor/bin/ece-tools run scenario/deploy.xml
# We run post deploy hook to clean and warm the cache. Available with ECE-Tools 2002.0.10.
post_deploy: |
php ./vendor/bin/ece-tools run scenario/post-deploy.xml

The goal of this bash is to:

  • Install NVM,
  • Install yarn and webpack,
  • Execute Magento OOTB build code,
  • Clone PWA Studio,
  • Build PWA Studio,
  • Clean PWA Studio directory to only keep the dist.

Install NVM

To do this, you first need to create a .environment file in Magento root directory with the following content :

# This is necessary for nvm to work.
unset NPM_CONFIG_PREFIX
# Disable npm update notifier; being a read only system it will probably annoy you.
export NO_UPDATE_NOTIFIER=1
# This loads nvm for general usage.
export NVM_DIR="$MAGENTO_CLOUD_APP_DIR/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

Then, create the file used in our .magento.app.yml in .hooks/bin/build.sh (obviously, you can put this file anywhere you want but don’t forget to use the good path in the yaml configuration). Then, add the following lines :

#!/bin/dash

### INSTALL NVM TO UPGRADE NODE JS ###
unset NPM_CONFIG_PREFIX
export NVM_DIR="$MAGENTO_CLOUD_APP_DIR/.nvm"
# install.sh will automatically install NodeJS based on the presence of $NODE_VERSION
curl -f -o- https://raw.githubusercontent.com/nvm-sh/nvm/$NVM_VERSION/install.sh | bash
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
### END INSTALL NVM TO UPGRADE NODE JS ###

Return to the .magento.app.yml and find the variables node, add the NODE and NPM version, it should be like this :

# Environment variables
variables:
env:
NVM_VERSION: v0.36.0
NODE_VERSION: v14.13.1
NODE_ENV: "production"
# Others variables

Install Yarn

Those tools will allow you to build your application. To install them, put those lines in the .hooks/bin/build.sh :

### INSTALL YARN & WEBPACK ###
npm install --global yarn
### END INSTALL YARN & WEBPACK ###

Execute Magento OOTB logic

We need to keep Magento logic to execute some stuff like installing composer dependencies. So put those lines in the .hooks/bin/build.sh :

### MAGENTO OOTB LOGIC ###
php ./vendor/bin/ece-tools run scenario/build/generate.xml
php ./vendor/bin/ece-tools run scenario/build/transfer.xml
### END MAGENTO OOTB LOGIC ###

Clone, build and clean PWA Studio

### INSTALL PWA STUDIO ###
if [ -z "${PWA_BRANCH}" ];
then
PWA_BRANCH='production'
echo "PWA_BRANCH Not exist !"
fi
git clone --single-branch --branch $PWA_BRANCH https://your-repo-url.com/path-to-your-repo $MAGENTO_CLOUD_APP_DIR/pwa
cd pwa && yarn cache clean && yarn install --production=false --frozen-lockfile && echo yes|yarn build

### CHECK IF DIST WAS CREATED ###
if [ -d $MAGENTO_CLOUD_APP_DIR/pwa/dist ]
then
# Clean sources and preserve only dist directory
find $MAGENTO_CLOUD_APP_DIR/pwa -mindepth 1 ! -regex "^$MAGENTO_CLOUD_APP_DIR/pwa/dist\(/.*\)?" -delete
# Move statics files to make them accessible in magento pub directory
cp -R $MAGENTO_CLOUD_APP_DIR/pwa/dist/*.png $MAGENTO_CLOUD_APP_DIR/pub
else
echo "A problem occurred while building PWA Studio"
exit 1
fi
### ENDCLONE & INSTALL PWA STUDIO ###

Explanation :

1. We clone our PWA sources and take the branch associated on it’s repository. As we’re on Magento Cloud, we have created branches according to the taken architecture (pro or starter),

2. We enter in the previously created PWA directory and build the application. We forced the –production=false to prevent having errors, which break the dist directory creation, when NODE_ENV is set to production,

3. We remove all the sources from the PWA Studio repository to only keep the desired directory which is the dist one,

4. We add a security to prevent deploying successfully if an error occurred during the build which will stop the deployment.

Full content & deployment

Here is the full content of each needed file. Considering we’re on Magento root directory :.magento.app.yml

# Environment variables
variables:
env:
NVM_VERSION: v0.36.0
NODE_VERSION: v14.13.1
# Using gitlab ? Feel free to put your token here :) (optional)
# You can also handle this with variables
GITLAB_TOKEN: A_BEAUTIFUL_TOKEN
GITLAB_USERNAME: AN_AMAZING_USER
# end (optional)
# You can handle this value with variables
CHECKOUT_BRAINTREE_TOKEN: sandbox_token
ENABLE_EXPRESS_SERVER_COMPRESSION: false
IMAGE_OPTIMIZING_ORIGIN: backend
MAGENTO_BACKEND_EDITION: EE
NODE_ENV: "production"
# You can handle this value with variables
CONFIG__DEFAULT__WEB__UPWARD__PATH: "/path/to/magento/root/pwa/dist/upward.yml"
.hooks/bin/build.sh

#!/bin/dash

### INSTALL NVM TO UPGRADE NODE JS ###
unset NPM_CONFIG_PREFIX
export NVM_DIR="$MAGENTO_CLOUD_APP_DIR/.nvm"
# install.sh will automatically install NodeJS based on the presence of $NODE_VERSION
curl -f -o- https://raw.githubusercontent.com/nvm-sh/nvm/$NVM_VERSION/install.sh | bash
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
npm install --global yarn
### END INSTALL NVM TO UPGRADE NODE JS ###

### run the build tasks using Composer 2.x. (Magento >=2.4.2) ###
composer --no-ansi --no-interaction install --no-progress --prefer-dist --optimize-autoloader
### end using composer 2.x. ###

### MAGENTO OOTB LOGIC ###
php ./vendor/bin/ece-tools run scenario/build/generate.xml
php ./vendor/bin/ece-tools run scenario/build/transfer.xml
### END MAGENTO OOTB LOGIC ###

### INSTALL PWA STUDIO ###
if [ -z "${PWA_BRANCH}" ];
then
PWA_BRANCH='integration'
echo "PWA_BRANCH Not exist !"
fi
git clone --single-branch --branch $PWA_BRANCH https://your-repo-url.com/path-to-your-repo $MAGENTO_CLOUD_APP_DIR/pwa
cd pwa && yarn cache clean && yarn install --production=false --frozen-lockfile && echo yes|yarn build

### CHECK IF DIST WAS CREATED ###
if [ -d $MAGENTO_CLOUD_APP_DIR/pwa/dist ]
then
# Clean sources and preserve only dist directory
find $MAGENTO_CLOUD_APP_DIR/pwa -mindepth 1 ! -regex "^$MAGENTO_CLOUD_APP_DIR/pwa/dist\(/.*\)?" -delete
# Move statics files to make them accessible in magento pub directory
cp -R $MAGENTO_CLOUD_APP_DIR/pwa/dist/*.png $MAGENTO_CLOUD_APP_DIR/pub
else
echo "A problem occurred while building PWA Studio"
exit 1
fi
### ENDCLONE & INSTALL PWA STUDIO ###
.environment

# This is necessary for nvm to work.
unset NPM_CONFIG_PREFIX
# Disable npm update notifier; being a read only system it will probably annoy you.
export NO_UPDATE_NOTIFIER=1
# This loads nvm for general usage.
export NVM_DIR="$MAGENTO_CLOUD_APP_DIR/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

DEPLOY! 🚀

DND - Magento Cloud x PWA Studio - release

Conclusion

Magento Cloud CI allow us to do many things via their available hooks which make it powerful although we might want less restriction to install packages (with apt-get or whatever, not available in any phases). You can notice several points in hosting PWA Studio on this solution:

  • Upward connector reduce performance because PHP is used to render and fetch but allow you to easily implement SSR via prerender.io
  • You can put all GraphQL queries (not mutations) in cache with faslty on pro architecture
  • The documentation provided by Magento Cloud is sometimes not complete or incorrect but is strongly supported by Platform.sh one.

Interested by PWA Studio or by Adobe Commerce (Magento) ?

As a certified Adobe Commerce (Magento) agency, Dn’D can assist you in your E-Commerce website consulting, design and maintenance.

Vous avez aimé ?

0