DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations

Trending

  • Writing a Vector Database in a Week in Rust
  • How To Approach Java, Databases, and SQL [Video]
  • RBAC With API Gateway and Open Policy Agent (OPA)
  • Comparing Cloud Hosting vs. Self Hosting

Trending

  • Writing a Vector Database in a Week in Rust
  • How To Approach Java, Databases, and SQL [Video]
  • RBAC With API Gateway and Open Policy Agent (OPA)
  • Comparing Cloud Hosting vs. Self Hosting
  1. DZone
  2. Software Design and Architecture
  3. Performance
  4. Optimize Ghost Blog Performance Including Rewriting Image Domains to a CDN

Optimize Ghost Blog Performance Including Rewriting Image Domains to a CDN

Sometimes, ghost blogging is too lean for our requirements. Follow these steps to optimize a Ghost Blog's performance while keeping it lean and resourceful.

Sudip Sengupta user avatar by
Sudip Sengupta
CORE ·
Updated Jun. 17, 20 · Tutorial
Like (2)
Save
Tweet
Share
6.80K Views

Join the DZone community and get the full member experience.

Join For Free

The Ghost blogging platform offers a lean and minimalist experience. And that's why we love it. But unfortunately, sometimes, it can be too lean for our requirements.

Web performance has become more important and relevant than ever, especially since Google started including it as a parameter in its SEO rankings. We make sure to optimize our websites as much as possible, offering the best possible user experience. This article will walk you through the steps you can take to optimize a Ghost Blog's performance while keeping it lean and resourceful.

When we started working on the appfleet blog we began with a few simple things:

Ghost Responsive Images

The featured image in a blog has lots of parameters, which is a good thing. For example, you can set multiple sizes in package.json and have Ghost automatically resize them for a responsive experience for users on mobile devices or smaller screens.

HTML
 




xxxxxxxxxx
1
23


 
1
"config": {
2
        "posts_per_page": 10,
3
        "image_sizes": {
4
            "xxs": {
5
                "width": 30
6
            },
7
            "xs": {
8
                "width": 100
9
            },
10
            "s": {
11
                "width": 300
12
            },
13
            "m": {
14
                "width": 600
15
            },
16
            "l": {
17
                "width": 900
18
            },
19
            "xl": {
20
                "width": 1200
21
            }
22
                 }
23
}


And then, all you have to do is update the theme's code

HTML
 




xxxxxxxxxx
1


 
1
<img class="feature-image"
2
    srcset="{{img_url feature_image size="s"}} 300w,
3
            {{img_url feature_image size="m"}} 600w,
4
            {{img_url feature_image size="l"}} 900w,
5
            {{img_url feature_image size="xl"}} 1200w"
6
    sizes="800px"
7
    src="{{img_url feature_image size="l"}}"
8
    alt="{{title}}"
9
/>



Common HTML Tags for Performance

Next, we take a few simple steps to optimize Asset Download Time. That includes adding preconnect and preload headers in default.hbs:

HTML
 




xxxxxxxxxx
1


 
1
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin="anonymous">
2
<link rel="preconnect" href="https://cdn.jsdelivr.net/" crossorigin="anonymous">
3
<link rel="preconnect" href="https://widget.appfleet.com/" crossorigin="anonymous">
4

            
5
<link rel="preload" as="style" href="https://fonts.googleapis.com/css?family=Red+Hat+Display:400,500,700&display=swap" />
6
<link rel="preload" as="style" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.13.0/css/all.min.css" />


As we load many files from jsDelivr to improve our performance, we instruct the browser to establish a connection with the domain as soon as possible. The same goes for Google Fonts and the sidebar widget that was custom coded.

Most often than not, users coming from Google or some other source to a specific blog post will navigate to the homepage to check what else we have written. For the same reason, on blog posts, we also added prefetch and prerender tags for the main blog page. 

That way the browser will asynchronously download and cache it, making the next most probable action of the user almost instant:

HTML
 




xxxxxxxxxx
1


 
1
<link rel="prefetch" href="https://appfleet.com/blog">
2
<link rel="prerender" href="https://appfleet.com/blog">




To solve this problem we took two steps. Lazy load the images and use a CDN. The issue is that the Ghost doesn't allow to modify or filter the contents of the post. All you can do is output the HTML.

The easiest solution to this is to use a dynamic content CDN like Cloudflare. A CDN will proxy the whole site, won't cache the HTML, but cache all static content like images. They also have an option to lazy load all images by injecting their Javascript.

But we didn't want to use Cloudflare in this case. And didn't feel like injecting third-party JS to lazy load the images either. So what did we do?


Nginx to the Rescue!

Our blog is hosted on a DigitalOcean droplet created using its marketplace apps. It's basically an Ubuntu VM that comes pre-installed with Node.js, NPM, Nginx, and Ghost.

Note that even if you don't use DigitalOcean, you are still recommended to use Nginx in-front of the Node.js app of Ghost.

This eventually makes the solution pretty simple. We use Nginx to rewrite the HTML, along with enabling a CDN and lazy-loading images at the same time, without any extra JS.

For CDN, you may also use the free CDN offered by Google to all AMP projects. Not many people are aware that you can use it as a regular CDN without actually implementing AMP. 

All you have to do is use this URL in front of your images:

https://appfleet-com.cdn.ampproject.org/i/s/appfleet.com/

Replace the domains with your own and change your <img> tags, and you are done. All images are now served through Google's CDN.

The best part is that the images are not only served but optimized as well. Additionally, it will even serve a WebP version of the image when possible, further improving the performance of your site.

As for lazy loading, you may use the native functionality of modern browsers that looks like this <img loading="lazy". By adding loading="lazy" to all images, you instruct the browsers to automatically lazy load them once they become visible by the user.

And now the code itself to achieve this:

HTML
 




xxxxxxxxxx
1
22


 
1
server {
2
    listen 80;
3

              
4
    server_name NAME;
5

              
6
    location ^~ /blog/ {
7
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
8
        proxy_set_header X-Real-IP $remote_addr;
9
        proxy_set_header Host       "appfleet.com";
10
        proxy_set_header        X-Forwarded-Proto https;
11
        proxy_pass http://127.0.0.1:2368;
12
        proxy_redirect off;
13
        
14
        #disable compression 
15
        proxy_set_header Accept-Encoding "";
16
        #rewrite the html
17
        sub_filter_once off;
18
        sub_filter_types text/html;
19
        sub_filter '<img src="https://appfleet.com' '<img loading="lazy" data-fr-src="https://appfleet-com.cdn.ampproject.org/i/s/appfleet.com';
20
    }
21

              
22
}



First, we disable compression between Node.js and Nginx. If not done, Nginx can't modify the HTML if it comes in binary form. 

Next, we use the sub_filter parameter to rewrite HTML. Additionally in line#19 above, we enabled both the CDN and lazyloading. Reload the config and you are good to go. 

Check Appfleet to see the configured performance in real-time.

I would be delighted to know your experience with the configuration above. 


Content delivery network Ghost (disk utility) Blog

Published at DZone with permission of Sudip Sengupta. See the original article here.

Opinions expressed by DZone contributors are their own.

Trending

  • Writing a Vector Database in a Week in Rust
  • How To Approach Java, Databases, and SQL [Video]
  • RBAC With API Gateway and Open Policy Agent (OPA)
  • Comparing Cloud Hosting vs. Self Hosting

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: