Integrating SpreeCommerce Store with AWS CloudFront CDN

When your website receives thousands of visitors every day from around the world, we need to ensure that the experience does not deteriorate based on the geographical location of the user. But the reality is bitter and geographical location does plays a role in website’s responsiveness.

Why does the geography comes in play when we are showing same content to anyone accessing the site. It’s due to the latency at the network level, also known as “Fibre Optic Latency”. Same data needs to travel a large distance for one user as the server location is fixed.

We will explore how can we use Content Delivery Network to provide a virtual feeling of server closeness for every user irrespective of different geographical location.

Content Delivery Network allows you to serve the cached content from the edge locations close to user which are also known as Point of Presence, PoP. It reduces the load times, hence, adds to better user experience which reflects in revenues too :)

CDN Edge Cache Servers and Users

Image sourced from here

Let’s see how can we setup AWS Couldfront (CDN) along with AWS S3 storage for SpreeCommerce.

Setup

SpreeCommerce has made it convenient for us by choosing paperclip for managing media assets.

Also, AWS S3 is the de-facto choice to store assets like images, videos, audios etc due to its high availability and high performance.

So we will be exploring techniques and changes related to paperclip to serve assets on AWS S3 via AWS CloudFront

Let’s ensure that:

  • We have created a S3 bucket to store our assets (css/js/images etc)
  • We have created a AWS CloudFront distribution to serve our assets
  • We have set the AWS CloudFront distribution to use our Amazon S3 bucket as Origin to retrieve assets if its not already cached with Cloudfront.

SpreeCommerce Customization

We should explore where all our assets are being managed and plan to have them on AWS S3 when AWS Cloudfront needs them.

We will list out some of the assets and tools which can be easily found in almost all SpreeCommerce stores and should be configured to use with CDN.

  • Spree Store Assets like stylesheets, javascripts, images and other.
  • Spree::Image which is used to store product and variant images
  • Spree::Taxon which has icon image
  • There could be Spree extensions which introduces their Paperclip models or editors which are used to manage assets like CKEditor

Basically, we need to ZERO down on the possibilities of asset references across our Spree Store & extensions and make sure that they are present on AWS S3 after deploy or as they are created from our Spree Store.

Don’t be disheartened, it’s not that tedious as it looks.

  • You can start with finding references of has_attached_file and start overriding url option as ":s3_alias_url"

    • We can use the decorator pattern to override the url option for code we don’t manage directly and change the code directly where we own it

      # app/models/spree/image_decorator.rb
      # Code we don't own and part of Spree::Core
      Spree::Image.class_eval do
        attachment_definitions[:attachment][:url] = ':s3_alias_url'
      end
      # app/models/ckeditor/picture.rb
      # Code we might be owning if configured CKEdior manually
      # It might also come from Spree Extension like spree_editor
      class Ckeditor::AttachmentFile < Ckeditor::Asset
        ... # Some code
      
        has_attached_file :data,
          url: ':s3_alias_url'
      
        ... # Rest of the code
      end
  • Make sure that config/environments/production.rb is configured to use paperclip as

    config.paperclip_defaults = {
      storage: :s3,
      url: ':s3_alias_url',
      s3_host_alias: 'cloudfront_distribution.cloudfront.net',
      bucket: "<%= ENV['CDN_AWS_BUCKET'] %>"
    }
  • Set the asset_host in config/environments/production.rb for Mailers and Rails Asset Pipeline to have correct url for stylesheets, javascripts, images etc both in the application and mailers.

    config.action_mailer.asset_host = 'https://cloudfront_distribution.cloudfront.net'
    config.action_controller.asset_host = 'https://cloudfront_distribution.cloudfront.net'
  • Use asset_sync gem to move compiled Rails assets to S3 with ease as part of deploy process.

    AssetSync.configure do |config|
      config.fog_provider = 'AWS'
      config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
      config.aws_secret_access_key = ENV['AWS_SECRET_KEY']
      config.fog_directory = ENV['CDN_AWS_BUCKET']
      config.fog_region = ENV['AWS_S3_REGION']
      config.enabled = true
      config.aws_reduced_redundancy = true
      config.existing_remote_files = 'keep'
      config.gzip_compression = true
      config.manifest = true
      config.fail_silently = true
      config.run_on_precompile = true
    end
  • Also, ensure that assets are set as public on AWS S3 to be picked by AWS Cloudfront

  • You might need to set following CORS Policy in S3 bucket CORS configuration editor if CORS issue encountered while serving assets using AWS CloudFront

    <?xml version="1.0" encoding="UTF-8"?>
     <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
         <CORSRule>
             <AllowedOrigin>*</AllowedOrigin>
             <AllowedMethod>GET</AllowedMethod>
             <MaxAgeSeconds>3000</MaxAgeSeconds>
             <AllowedHeader>Authorization</AllowedHeader>
         </CORSRule>
     </CORSConfiguration>

Enjoy the snappy page loads for your Spree Store !!

References

Leave a Reply

Your email address will not be published. Required fields are marked *