Resolve CORS fonts issue on Firefox (and now Chrome too) with Rails assets pipeline


Update

If you are having this issue with CloudFront and you have access to Nginx or Apache server, you should read this post: Correct configuration to fix CORS issue with CloudFront


When using custom fonts such as FontAwesome or Glyphicon, you might realize that some icons disappear on Firefox (or newest version of Chrome). The issue is because of something called Cross-Origin Resource Sharing. By default, Firefox will stop your fonts from loading if that font is hosted on different domain from your website and the server containing the fonts is not configured with Access-Control-Allow-Origin. Here is the warning you might see:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://fonts.gstatic.com/s/newscycle/v12/G28Ny31cr5orMqEQy6ljt3bFhgvWbfSbdVg11QabG8w.woff. This can be fixed by moving the resource to the same domain or enabling CORS.

The issues often occurs whenever I try to put my asset on CDN because I want to host all assets (CSS+JS) on different servers for faster loading. If you are using AWS CloudFront, you might see the link to your assets like this xxxx.cloudfront.net. And obviously, this domain is different from your website and some browsers like Firefox would not allow the fonts to be loaded

I even tried a method suggested by other users on the Internet such as setting CORS header on Amazon S3 (http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html) but for some reasons it did not work properly on my case. I actually did not know why it does not work with me while many users on the Internet saying that it worked with them. So I had to look for another way. And there are two possible solutions

First of all, if you have access to your server and you can update Nginx or Apache config, you can add Access-Control-Allow-Origin header to the assets to let Firefox and other browsers understand that this resource can be shared on different domain. Example: http://lukasz.cepowski.com/devlog/50,simple-cdn-with-nginx-that-allows-cors

Lastly, you can try following hack which I believe will always work. I do not think this is the best way to solve this issue but at least it always work and my customers feel happy with that. Basically, I tackle the root cause of the issue: place the fonts on the same server with the main site. Here are the steps:

  1. Create a CSS file called fonts.css in your app which is just like normal CSS, but do not require this file in your application.css. Copy other CSS in other files used for loading fonts and put them into this fonts.css, for example

     @font-face {
        font-family: 'entypo';
        src: url('/fonts/entypo.eot?71205724');
        src: url('/fonts/entypo.eot?71205724#iefix') format('embedded-opentype'),
            url('/fonts/entypo.woff?71205724') format('woff'),
            url('/fonts/entypo.ttf?71205724') format('truetype'),
            url('/fonts/entypo.svg?71205724#entypo') format('svg');
        font-weight: normal;
        font-style: normal;
     }
    

Update
You can also create fonts.css inside your public folder instead of app/stylesheets

  1. Create a normal link tag inside your application.html.erb layout like this

     <link href='/assets/fonts.css' rel='stylesheet' type='text/css' />
    
  2. Feel the awesomeness. Your problem of loading fonts from other host has already gone away.

I applied this method for more than 3 different projects and they all work properly. Let me know if this solve your problem. If you have any better suggestion, feel free to let me and other users know.