heroku 为什么我从Aws加载css/js时,Django/React应用程序会出现MIME类型错误?

gwo2fgha  于 2022-11-13  发布在  Go
关注(0)|答案(1)|浏览(118)

因此,我在Heroku上部署了Django-Rest/React应用,在那里我将静态和媒体文件放在AWS S3桶上。在推送到Heroku并访问API URL或管理URL后,一切都正常,但当我尝试访问我的React URL时,我得到了一个MIME类型的错误。
在开发者工具的网络选项卡上,我的JS和CSS文件的状态为301。
在控制台中,我得到:

Refused to apply style from 'https://app.herokuapp.com/static/css/main.9d3ee958.css/' because its MIME type 
('text/html') is not a supported stylesheet MIME type, and strict MIME checking is 
enabled.
app.herokuapp.com/:1 Refused to apply style from 'https://app.herokuapp.com/static/css/main.9d3ee958.css/' because its MIME type 
('text/html') is not a supported stylesheet MIME type, and strict MIME checking is 
enabled.
app.herokuapp.com/:1 Refused to execute script from 'https://app.herokuapp.com/static/js/main.3b833115.js/' because its MIME type 
('text/html') is not executable, and strict MIME type checking is enabled.

即使上面的URL是正确的,我确实有这些文件在我的桶。
以下是我的制作设置:

from decouple import config
import django_heroku
import dj_database_url
from .base import *

 SECRET_KEY = config('SECRET_KEY')
 DEBUG = False

 ALLOWED_HOSTS = ['*']

 ROOT_URLCONF = 'portfolio.urls_prod'

 TEMPLATES = [
     {
         'BACKEND': 'django.template.backends.django.DjangoTemplates',
         'DIRS': [
             os.path.join(BASE_DIR, 'frontend/build')
         ],
         'APP_DIRS': True,
         'OPTIONS': {
             'context_processors': [
                 'django.template.context_processors.debug',
                 'django.template.context_processors.request',
                 'django.contrib.auth.context_processors.auth',
                 'django.contrib.messages.context_processors.messages',
             ],
         },
     },
 ]

 # DATABASE
 DATABASES = {}
 DATABASES['default'] = dj_database_url.config(conn_max_age=600)

 # HEROKU
 django_heroku.settings(locals())

 # AWS S3 SETTINGS
 AWS_ACCESS_KEY_ID = config('AWS_ACCESS_KEY_ID')
 AWS_SECRET_ACCESS_KEY = config('AWS_SECRET_ACCESS_KEY')
 AWS_STORAGE_BUCKET_NAME = config('AWS_STORAGE_BUCKET_NAME')
 AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
 AWS_DEFAULT_ACL = 'public-read'

 AWS_S3_OBJECT_PARAMETERS = {
     'CacheControl': 'max-age=86400',
 }
 AWS_HEADERS = {
     'Access-Control-Allow-Origin': '*',
 }
 AWS_QUERYSTRING_AUTH = False

 # AWS STATIC SETTINGS
 AWS_LOCATION = 'static'
 STATIC_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)
 STATICFILES_STORAGE = 'portfolio.storage_backend.StaticStorage'

 # AWS MEDIA SETTINGS
 DEFAULT_FILE_STORAGE = 'portfolio.storage_backend.MediaStorage'
 MEDIA_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, 'media')

 STATICFILES_DIRS = [
     os.path.join(BASE_DIR, 'frontend/build/static'),
 ]

 # HEROKU LOGGING
 DEBUG_PROPAGATE_EXCEPTIONS = True

 LOGGING = {
     'version': 1,
     'disable_existing_loggers': False,
     'formatters': {
         'verbose': {
             'format' : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
             'datefmt' : "%d/%b/%Y %H:%M:%S"
         },
         'simple': {
             'format': '%(levelname)s %(message)s'
         },
     },
     'handlers': {
         'console': {
             'level': 'DEBUG',
             'class': 'logging.StreamHandler',
         },
     },
     'loggers': {
         'MYAPP': {
             'handlers': ['console'],
             'level': 'DEBUG',
         },
     }
 }

 # HTTPS SETTING
 SESSION_COOKIE_SECURE = True
 CSRF_COOKIE_SECURE = True
 SECURE_SSL_REDIRECT = True

 # HSTS SETTINGS
 SECURE_HSTS_SECONDS = 31536000 # 1 year
 SECURE_HSTS_PRELOAD = True
 SECURE_HSTS_INCLUDE_SUBDOMAINS = True

 options = DATABASES['default'].get('OPTIONS', {})
 options.pop('sslmode', None)

这是我的storage_backend.py代码:

from storages.backends.s3boto3 import S3Boto3Storage

class MediaStorage(S3Boto3Storage):
    location = 'media'
    file_overwrite = False

class StaticStorage(S3Boto3Storage):
    location = 'static'
    default_acl = 'public-read'

这是我的url_prod.py代码:

from django.contrib import admin
from django.urls import path, re_path, include
from django.views.generic import TemplateView
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
  path("admin/", admin.site.urls),
  path('api/', include('api.urls')),

  re_path(r'^(?P<path>.*)/$', TemplateView.as_view(template_name='index.html')),
  path('', TemplateView.as_view(template_name='index.html')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

这是我的斗策:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowPublicRead",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::bucket-name/*"
        }
    ]
}

编辑:

我检查了开发者工具中的网络选项卡,发现管理员的静态文件正在从我的was bucket中提供服务:

Request URL: 
https://bucket-name.s3.amazonaws.com/static/admin/css/base.css
Request Method: GET
Status Code: 200 OK (from disk cache)
Remote Address: 52.95.143.47:441
Referrer Policy: same-origin

但我的React视图的静态文件不是:

Request URL: 
https://app.herokuapp.com/static/css/main.9d3ee958.css
Request Method: GET
Status Code: 301 Moved Permanently
Remote Address: 54.224.34.30:441
Referrer Policy: same-origin
smtd7mpg

smtd7mpg1#

所以我决定回答我自己的问题,以防有人看到这个,也有同样的问题。
问题是每当我运行“npm run build”时,React都在创建我的index.html,其中js和CSS文件都链接到build文件夹中我的本地路径。
因此,经过大量研究,我决定在react应用的根目录下创建一个.env文件,并使用以下设置:

PUBLIC_URL=https://path-to-bucket.s3.amazonaws.com

现在每次我运行build react时,都会在我的js和CSS文件中将这个URL添加到“src”中。
在添加此设置之前:

<html lang="en">
<head>
    
    <script defer="defer" src="../static/js/main.d91dacb2.js"></script>
    <link href="../static/css/main.9d3ee958.css" rel="stylesheet" />
</head>
<body>
    <div id="root"></div>
</body>

添加此设置后:

<html lang="en">
<head>
    
    <script defer="defer" src="https://path-to-bucket.s3.amazonaws.com/static/js/main.d91dacb2.js"></script>
    <link href="https://path-to-bucket.s3.amazonaws.com/static/css/main.9d3ee958.css" rel="stylesheet" />
</head>
<body>
    <div id="root"></div>
</body>

但我的图片仍然没有加载,所以我决定创建一个函数,检查应用程序是否在开发或生产中运行,并为每种情况创建一个URL:

export const dynamicUrl = (name) => {
  let url

  if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') {
    
    url = `../static/images/${name}`

  } else {
    
    url = `https://path-to-bucket.s3.amazonaws.com/static/images/${name}`
  }
  return url
};

NODE_ENV是procces.env附带的一个变量,用于检查环境。
希望这能帮助那些和我有同样问题的人。

相关问题