5 Steps To Setup Amazon CloudFront in Magento 2 and Clean CDN Cache

5 min read

Send to you:

Often, when we need to speed up the website performance, it’s a good idea to relocate the static content, such as images, CSS and JavaScript files, from your website domain. We can put this content to some external content distribution network (CDN). In our case, we can rely on Amazon CDN services.

Amazon provides their CDN solution called Amazon CloudFront CDN which is the part of their AWS services. But if we need to make some changes in the content of static resources, we must also update them on the CDN side. We are glad to introduce Magento® 2 module which solves this problem.

Our task for today is to clean Amazon CloudFront Cache in order to make it empty. We should break it into two phases. The first one is settings on the Amazon side, and the second one is the most interesting – configuring Magento 2 module. Let’s start our project!

Setting Up Amazon CloudFront for Magento 2

First of all, we need to config CloudFront Distribution on Amazon side. We can configure the one CloudFront Distribution for the one domain name. That’s why in case there are several websites hosted on Magento, we should create the apart CloudFront Distribution for each domain name. Each CloudFront Distribution will have the unique identifier which we can use later for API requests.

URL which represents CloudForm Distribution should be defined on Magento side:

Stores -> Configuration -> General -> Web -> Base URLs.

We should define it in Base URL for Static View File and Base URL for User Media Files fields. We should write this URL for both cases, secure and unsecure URLs. After that, the static content will be requested by the CDN URL. If the content is not there, Amazon CloudFront will request it from the website and then cache it.

Finally, we should generate the key pair on the Amazon side. It’s a secret key for connecting to Magento using Amazon API.

Creating Magento 2 Module for Using Amazon CloudFront CDN

First, we’ll need the AWS SDK library to implement Magento 2 module for CDN. The easiest way to install the AWS SDK library on Magento 2 is to add the row to the “require” section of composer.json file. We should add the following row:

“aws/aws-sdk-php”: “3.x”

Then we should run the “composer update” command in the console. The AWS library will be successfully uploaded to vendor/aws directory.

Now we can move to Magento 2 module implementation. The module will consist of:

  • a system configuration;
  • a block which we’ll display on cache management page in admin panel;
  • a controller which will process the form submit.

So, what’s then? We’ll go through each step providing the code samples. Ready-steady-go!

Magento 2 System Configuration for Amazon CloudFront CDN

etc/admihtml/system.xml file will look like the following:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
    <system>
        <section id="amazoncloudfront" translate="label" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1">
            <label>Amazon Cloudfront</label>
            <tab>mg_extensions</tab>
            <resource>Web4pro_Cloudfront::config</resource>
            <group id="general" translate="label" sortOrder="110" showInDefault="1" showInWebsite="1" showInStore="1">
                <label>General</label>
                <field id="enabled" translate="label comment" type="select" sortOrder="10" showInDefault="1">
                    <label>Enable Amazon Cloudfront Cache Invalidate</label>
                    <source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
                </field>
                <field id="access_key" translate="label comment" type="text" sortOrder="20" showInDefault="1">
                    <label>Access Key</label>
                </field>
                <field id="secret_access_key" translate="label comment" type="text" sortOrder="30" showInDefault="1">
                    <label>Secret Access Key</label>
                </field>
                <field id="amazon_region" translate="label comment" type="text" sortOrder="40" showInDefault="1">
                    <label>Amazon Region</label>
                </field>
                <field id="identifier" translate="label comment" type="text" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1">
                    <label>Amazon Cloudfront Identifier</label>
                </field>
            </group>
        </section>
    </system>
</config>

This configuration allows the user to turn on or turn off the module in Magento 2, set and generate Access Key and Secret Key on the Amazon side, define the region.

Amazon requires specifying the region for connection because not all AWS services are available for all regions. Fortunately, Amazon CloudFront is available in all valid regions. For instance, we can specify us-east-1. All configuration parameters are global, except the identifier which we can specify for any store view. As said before, each domain should have the apart identifier on Amazon CloudForm. That’s why ids are unique.

Displaying the Block on Cache Management Page in Magento 2

Now, let’s display the block on the cache management page in the admin panel. We can do it with “layout adminhtml cache index.xml” file where we’ll define the block and its template.

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="cache.additional">
            <block class="Web4pro\Cloudfront\Block\Cache" name="cache.cloudfront" template="Web4pro_Cloudfront::cache.phtml"/>
        </referenceBlock>
    </body>
</page>

We’ll define “canShow” method in the block. This method will check whether the module is turned on by the administrator or not.

public function canShow(){
        return $this->_scopeConfig->getValue('amazoncloudfront/general/enabled');
    }

The template will look like the following way:

if($this->canShow()):?>
<form method="post" action="<?php echo $this->getUrl('cloudfront/index/flush'); ?>">
    <h3><?php echo __('Enter paths to files you want to invalidate on Amazon Cloudfront Side. Each new path you should specify from new line.'); ?></h3>
    <input type="hidden" name="form_key" value="<?php echo $this->getFormKey(); ?>"/>
    <textarea name="files" rows="10" style="width:100%"></textarea>
    <button type="submit" class="button">
        <span><span><?php echo __('Flush'); ?></span></span>
    </button>
</form>
<?php endif;?>

The form in the admin panel should have “form_key” element, otherwise, the form will not be processed. “Textarea” element allows the administrator to specify the ways to files, which caches should be cleaned up on Amazon CloudForm side. So, we just need to implement the controller. Let’s do it.

Implementing Controller for Processing the Form Submit in Magento 2

We can implement the controller in the following way:

class Flush extends \Magento\Backend\App\Action {

    public function execute(){
        $files = $this->getRequest()->getPostValue();
        $logger = $this->_objectManager->get('Psr\Log\LoggerInterface');
        try{
            if(!isset($files['files'])){
                $this->getMessageManager()->addError(__("Files haven't been provided"));
            }else{
                $files = explode("\n",$files['files']);
                foreach($files as $k=>$file){
                    if(trim($file)==''){
                        unset($files[$k]);
                    }else{
                        $files[$k] = trim($file);
                    }
                }
                if(!count($files)){
                    $this->getMessageManager()->addError(__("Files haven't been provided"));
                }else{
                    $scopeConfig = $this->_objectManager->get('\Magento\Framework\App\Config\ScopeConfigInterface');
                    $params = array('version' => 'latest',
                        'region'=>$scopeConfig->getValue('amazoncloudfront/general/amazon_region'),
                        'credentials' => new \Aws\Credentials\Credentials(
                            $scopeConfig->getValue('amazoncloudfront/general/access_key'),
                            $scopeConfig->getValue('amazoncloudfront/general/secret_access_key')));
                    $client = new \Aws\CloudFront\CloudFrontClient($params);
                    $storeManager = $this->_objectManager->get('Magento\Store\Model\StoreManager');
                    $distributions = array();
                    foreach($storeManager->getStores() as $store){
                        $distribution = $scopeConfig->getValue('amazoncloudfront/general/identifier','store',$store->getId());
                        if(!in_array($distribution,$distributions)){
                            $distributions[] = $distribution;
                        }
                    }
                    foreach($distributions as $distribution){
                        $requestArray = array('DistributionId'=>$distribution,
                                              'InvalidationBatch'=>array('CallerReference'=>time(),
                                                    "Paths"=>array('Items'=>$files,'Quantity'=>count($files))));
                        $res = $client->createInvalidation($requestArray);
                    }
                    $this->getMessageManager()->addSuccess(__('All paths have been invalidated'));
                }
            }
        }catch(\Exception $e){
            $this->getMessageManager()->addError($e->getMessage());
            $logger->error($e);
        }
       $this->getResponse()->setRedirect($this->_redirect->getRefererUrl());
    }
}

As you can see, this controller creates the object of the \Aws\CloudFront\CloudFrontClient type with the use of configuration parameters. It works the following way. The controller sends the request for cleaning cache following the ways which administrator entered to the input field of “textarea” type. This request is sent for each apart identifier. If some errors arise, for example, you have no rights on the Amazon side, or the way is not correct, the library will through the exclusion with a message. And the admin will see this message.

The ways in “textarea” must always begin with “/” symbol. For example: ‘/media’ or ‘/static’.

SUM MARY

That’s all you need to know to create Magento 2 module for connection with Amazon CloudFront CDN and cleaning its cache. This will also help you to improve your Magento 2 website performance. Need assistance with modules? Our Magento 2 experts are ready to take care of your project and consult you regarding Magento 2 Extension Development.

Posted on: October 19, 2017

5.0/5.0

Article rating (1 Reviews)

Do you find this article useful? Please, let us know your opinion and rate the post!

  • Not bad
  • Good
  • Very Good
  • Great
  • Awesome