As recommended in the docs I’m trying to add a caché layer to my heroku deployment
They have 2 add-ons to do this:
I’m using this repo to test the deployment → https://github.com/frontity-demos/my-frontity-project
So, this deployment in Heroku → https://mighty-badlands-59259.herokuapp.com/
Performance report in default deployment (no addons)
Performance report after adding Edge plugin
⬢ my-frontity-project î‚ master ⦾ heroku addons:create edge:hobby
› Warning: heroku update available from 7.25.0 to 7.39.3.
Creating edge:hobby on ⬢ mighty-badlands-59259... $5/month
Successfully configured https://d19mgjkbf05ovs.cloudfront.net
Created edge-graceful-46203 as EDGE_AWS_ACCESS_KEY_ID, EDGE_AWS_SECRET_ACCESS_KEY, EDGE_DISTRIBUTION_ID, EDGE_URL
Use heroku addons:docs edge to view documentation
I don’t see any improvement after adding this addon
Do you think there are some settings I have to do in order to take more advantage of this plugin? Can you help me verify this plugin is a good/bad option?
How did you configured Fastly? Do you need cache-control
headers for that?
How is the server response time of both tests? Does it improve?
Ok, after reading more carefully the Edge documentation I think I understand it better.
By adding this addon you get automatically a new layer that will be in front of the heroku app. This “layer” is set in CloudFront and the URL of this CloudFront layer is provided by one of the environment variables set by Edge (EDGE_URL
)
⬢ my-frontity-project î‚ master ⦿ heroku config:get EDGE_URL
› Warning: heroku update available from 7.25.0 to 7.39.3.
https://d19mgjkbf05ovs.cloudfront.net
⬢ my-frontity-project î‚ master ⦿ curl -i https://d19mgjkbf05ovs.cloudfront.net
HTTP/2 200
content-type: text/html; charset=utf-8
content-length: 370736
server: Cowboy
date: Wed, 22 Apr 2020 07:14:56 GMT
via: 1.1 vegur, 1.1 86b86f43445d5446c8b16910b2a9b8f9.cloudfront.net (CloudFront)
vary: Accept-Encoding
x-cache: Hit from cloudfront
x-amz-cf-pop: MAD50-C1
x-amz-cf-id: gzY-3p7EdR6AcW7RcYqAvnjYc3gawwgFMiZ8P7NoHbjGTLga17Lq1w==
age: 31
<!doctype html>
<html lang="en">
...
</html>
This is the URL that actually provide performance improvements…
The thing is that in a real project you won’t want using this URL for the final user so you have to configure a custom domain as explained in the Edge docs
But for testing purposes, I think it’s verified that adding this addon is a good solution for adding a CDN layer in a Heroku deployment of a Frontity project
To check the status of the addon you can do
⬢ my-frontity-project î‚ master ⦿ heroku addons:open edge
› Warning: heroku update available from 7.25.0 to 7.39.3.
Opening https://addons-sso.heroku.com/apps/7f2d2ec8-ae7b-4259-89d0-d7c3f0bc2c8b/addons/4d011408-61c1-48f9-a365-937896171450...
which will open the proper URL in the browser where you can see the activitity of this layer and configure a few things
Awesome, great work
What options do you have?
The static assets should be set to immutable (or something like one year). It seems like they are not being cached yet:
And for the HTML response, does Cloudfront support state-while-revalidate
? If not, I guess my recommendation would be to set the expire to 5 minutes or so, but I would explain that in the docs so people can set it themselves.
I’ve discovered this tool → httpstat
that allows you to view the server response times in an easy way
Response times from CloudFront layer (203ms)
⬢ my-frontity-project î‚ master ⦿ httpstat https://d19mgjkbf05ovs.cloudfront.net/
Connected to 13.224.105.208:443 from 192.168.100.13:56803
HTTP/2 200
content-type: text/html; charset=utf-8
content-length: 370736
server: Cowboy
date: Wed, 22 Apr 2020 07:14:56 GMT
via: 1.1 vegur, 1.1 52523006e1ee5c08eea6e9267e18fabf.cloudfront.net (CloudFront)
vary: Accept-Encoding
x-cache: Hit from cloudfront
x-amz-cf-pop: MAD50-C1
x-amz-cf-id: tXMWCK2EkGtLAb-GGBpqIu-tpuiu-0UmDsw3EcYeBLs5ZGd9o_YsnQ==
age: 5997
Body stored in: /var/folders/zh/c0rwtffn1dq_nzr1fp8gz1zh0000gn/T/tmpLmaNrT
DNS Lookup TCP Connection TLS Handshake Server Processing Content Transfer
[ 30ms | 20ms | 51ms | 26ms | 76ms ]
| | | | |
namelookup:30ms | | | |
connect:50ms | | |
pretransfer:101ms | |
starttransfer:127ms |
total:203ms
Response times directly from Heroku (2905ms)
⬢ my-frontity-project î‚ master ⦿ httpstat https://mighty-badlands-59259.herokuapp.com/
Connected to 52.70.139.21:443 from 192.168.100.13:56917
HTTP/1.1 200 OK
Server: Cowboy
Connection: keep-alive
Content-Type: text/html; charset=utf-8
Content-Length: 370736
Date: Wed, 22 Apr 2020 08:55:22 GMT
Via: 1.1 vegur
Body stored in: /var/folders/zh/c0rwtffn1dq_nzr1fp8gz1zh0000gn/T/tmp7Se2wX
DNS Lookup TCP Connection TLS Handshake Server Processing Content Transfer
[ 69ms | 268ms | 446ms | 1088ms | 1034ms ]
| | | | |
namelookup:69ms | | | |
connect:337ms | | |
pretransfer:783ms | |
starttransfer:1871ms |
total:2905ms
Taking this into account:
I think the problem with the static files is that there’s this header cache-control: max-age=0
telling CloudFront not to cache these files
Do you know who is setting this header?
It seems CloudFront doesn’t support state-while-revalidate
Can we add custom headers to some responses?
For what I understand → Proof of concept on Pantheon + Deploy on Google Cloud Platform
this is something planned to do but still not available
Maybe the solution here could be creating a custom server uses server.js
as middleware and proxy requests by adding the proper headers in the responses (but this adds complexity to the whole workflow so having a way to customize headers directly from frontity would be the way to go here)
And yes, this whole thing about Cache layers, headers involved and how to set them is something that needs to be explained very well as it is an important part of the Frontity Architecture.
I’m thinking about adding a glossary section like → https://www.gatsbyjs.org/docs/glossary/
to explain things like stale-while-revalidate
Some interesting resources regading this:
Yes, Frontity is not adding any cache-control
headers as of today.
We didn’t add them because we thought about adding a @frontity/headers
package, but it requires first the server extensibility and that is not ready yet.
I guess that we could add default cache-control headers until that is added… no-cache
for the server and immutable
for the static assets for the hostings like Heroku that don’t have a way to add them.
But, is there a way to configure those headers in Cloudfront for now? Do you know why is it caching the HTML but not caching the static assets? What configuration options does it give you (if any)?
I’m going to discard this way of adding a CDN for now, because:
-
Edge is creating a Cloudfront distribution but the way to configure Cloudfront from that plugin is kind of complex, limited and not very well documented
-
Cloudfront itself is very powerful but very complex as well, so I think we should focus first on more easy solutions
Maybe configuring a CDN layer with a service like KeyCDN is a better option to start with
I think Fastly may be a good option too, because it is free up to $50 (as far as I know).
I still prefer KeyCDN though, because it works great with stale-while-revalidate
. But for a medium/large site, state-while-revalidate
is not really useful.
@juanma could you please remind me what do you need from me here? Some insight on how to configure KeyCDN?