cssangularamazon-s3amazon-cloudfrontmime-types

CSS MIME type error when serving site from S3 via CloudFront


When visiting my website customtimers.net I get the following error:

Refused to apply style from 'https://customtimers.net/styles.css' because its MIME type
('application/xml') is not a supported stylesheet MIME type, and strict MIME checking is enabled.

However, CSS seems to be working on the site just fine.

I'm using an S3 static website served via CloudFront for HTTPS.

In S3:

I used Angular to create the front-end so my index.html is pretty much what it generated by default:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Customizable Timers</title>
    <base href="/">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />
    <link rel="icon" type="image/x-icon" href="favicon.ico">
  </head>
  <body>
    <app-root></app-root>
  </body>
</html>

The css file is referenced in app-root (in the body above) which is:

<!DOCTYPE html>
<html lang="en" [attr.data-bs-theme]="theme">

    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
        <meta name="description" content="A website where you can create customizable online timers." />
        <meta name="author" content="Me!" />
        <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests" />
        
        <title>Customizable Timers</title>

        <!-- Font Awesome icons -->
        <script src="https://use.fontawesome.com/releases/v6.3.0/js/all.js" crossorigin="anonymous"></script>

        <!-- Google fonts-->
        <link href="https://fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet" type="text/css" />
        <link href="https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic" rel="stylesheet" type="text/css" />

        <!-- Core theme CSS (includes Bootstrap)-->
        <link href="/styles.css" rel="stylesheet" />
    </head>

    <body id="page-top">...more content...</body>
</html>

My angular.json file:

"styles": [
    "node_modules/bootstrap/dist/css/bootstrap.min.css",
    "node_modules/@fortawesome/fontawesome-free/css/all.min.css",
    "src/styles.css"
],

The stylesheet is from Bootstrap with some edits, if that matters.

I tried the following:

This is my first time deploying a site so I'm not sure where to go from here. Happy to supply more details.

Update: Here's more detail about the file and bucket policy.

File permissions: CSS file detail

I tried this both with and without the utf-8.

Bucket policy, straight from CloudFront:

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::custom-timers-s3/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::<#####>:distribution/<bucket id>"
                }
            }
        }
    ]
}

Solution

  • I ended up finding a work around but I'm still not sure why there was a problem to begin with.

    First build the output files:

    ng build --configuration production
    

    Some build files come out of Angular with random strings between the file name and type:
    name.<random string>.type.

    Angular output files

    These files are referenced appropriately in the output index.html.

    index.html

    The work around is to rename the styles file to styles.css without the random string.

    Edited Angular output files

    Then in the output index.html, rename the references to styles.css.

    Edited index.html

    Then upload the files to S3.