Delivering your Meteor CSS/JS bundles and Public assets through a CDN (Cloudfront)
Tags: javascript, aws, performance, webdev
Published: 2022-01-06 14:56:45

As many of you already know, one of the main issues when your web app and business start to grow is to manage performance. What may run well when you have a few users could go totally broke with a few hundred users. Also for web application you rarely have a unified usage of the app. You'll have plenty of peak of use and, even during these peaks, the experience has to stay great for all your users. 

At [revolin.io](https://www.revolin.io) we had to face multiple times these peaks and the first experience was not too pleasant, neither for us, nor for the users. While starting an activity all the players connected together to our server that had to send all the Meteor bundles of js and css to every single one of them. No caching, doing the same job a hundred times and reaching its full capacity pretty quickly. While it was handling all these first connections nothing else could happen and the app was frozen for multiple users. Of course we do learn from mistakes and after some researches we decided to implement a CDN, Cloudfront from AWS, in order to deliver our Meteor bundles which tends to be big for SPA (both the Meteor JS and Meteor CSS bundles). Simply plugged with Meteor it totally relieves your server from delivering the bigger chunks of your app and doesn't block it to continue with other jobs. This work was inspired by this great [post on the meteor forums](https://forums.meteor.com/t/scaling-meteorjs-7-000-concurrent-connections/53270) and with a lot of help from Paulishca from the exact same place.

We'll do a very basic config using the distribution name provided by Cloudfront, but you can also plug a custom domain name and SSL certificates for your CDN if you wish to do so.

_**TLDR: Loads of users at once, server broke when delivering js/css: needs caching!**_

There are two parts to the process:

1. Creating the CDN
2. Setting up your app to deliver assets from the CDN

## Creating your Cloudfront (CDN) distribution

The most complex part in order to set up this CDN was to know what settings to set in the Cloudfront config. Fortunately I got plenty of help from the forum and I could reach the following results. More than words I am mainly gonna show screenshots of how you need to set up:

### Origin
![setting up the origin](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/43idftzx600k5bvizpgn.png)

 As you can see in the first part we just mention the address of our app and fix it for HTTPS.

### Default cache behavior - settings

![setting up default cache behavior](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r3mepehl1ozpw8vk7e76.png)
You then define which protocol poly you want for your CDN and which are the allow HTTP methods. We decide to cache also the OPTIONS method.

### Default cache behavior - Cache key and origin requests

![setting up origin requests](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4xpmepk1jrrewply6s9g.png)
 
This one is a bit more tricky one, you have to define all the cache settings. here we're gonna manually add the headers and create some custom ones. You'll have to add all the 9 headers either from the list or to type then. We also later down set up the caching time of the assets.

### Settings

![general settings](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/07eir6v9ty93ab9mzga6.png)
 
In the last settings you define which zones you want your CDN to be served from. 
When all these steps are done you'll get a link for your distribution domain name, something like

> uniqueid.cloudfront.net

and that's from where your assets will be served.

## Setting up your Meteor app to serve the assets from the CDN

This part is actually pretty simple. On the server side you'll have to use the WebAppInternals to tell Meteor to deliver the assets the bundled JS and CSS from your newly created CDN:

```
import { Meteor } from "meteor/meteor";
import { WebAppInternals } from "meteor/webapp";

if (Meteor.isProduction) {
   WebAppInternals.setBundledJsCssUrlRewriteHook(url => {
      return `https://uniqueId.cloudfront.net${url}`;
   });
}
```

From there you can deploy your new version you can check the network tab in the chrome console and see that your Meteor bundled js and css are not delivered from your server anymore but from Cloudfront.

## Bonus - Serve assets from "/public" folder as well

Any images or asset that you have in your "/public" folder of your Meteor app will also be reachable through the CDN. So if you want your public assets to be cached as well, instead of doing a src like "/image/myimg.png" add your CDN in the source: `${MY_CDN_URL}/image/myimg.png` and they will be delivered from the CDN and cached as well.