微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

拒绝从'... / bundle.js'执行脚本,因为其MIME类型'text / html'无法执行,并且启用了严格的MIME类型检查

如何解决拒绝从'... / bundle.js'执行脚本,因为其MIME类型'text / html'无法执行,并且启用了严格的MIME类型检查

我有一个带有React / webpack前端和Django / python后端的应用程序。过去,它已成功部署到heroku。自从我在应用程序中执行任何操作以来已经有一段时间了,在最近进行一些更新之后,我想更新已部署的版本。 Heroku报告该应用程序已成功部署,但是当我尝试访问它时,出现错误

拒绝执行“ https://pairshead-2020.herokuapp.com/bundle.js”中的脚本,因为其MIME类型(“ text / html”)不可执行,并且启用了严格的MIME类型检查。

这是我的webpack.config.js:

const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: './src/app.js',context: path.resolve(__dirname,'frontend'),output: {
    filename: 'bundle.js',path: path.resolve(__dirname,'frontend/dist'),publicPath: '/'
  },devtool: 'source-maps',module: {
    rules: [
      { test: /\.js$/,loader: 'babel-loader',exclude: /node_modules/ },{ test: /\.css$/,loader: ['style-loader','css-loader'] },{ test: /\.s(a|c)ss$/,'css-loader','sass-loader'] },{ test: /\.woff2?$/,loader: 'file-loader' },{ test: /\.(jpg|png|gif)$/,loader: 'file-loader' }
    ]
  },devServer: {
    contentBase: 'src',hot: true,open: true,port: 8000,watchContentBase: true,historyApiFallback: true,proxy: {
      '/api': 'http://localhost:4000'
    }
  },plugins: [
    new webpack.HotModuleReplacementPlugin(),new HtmlWebpackPlugin({
      template: 'src/index.html',filename: 'index.html',inject: 'body'
    })
  ]
}

这是我的package.json:

{
  "name": "results","version": "1.0.0","main": "index.js","license": "MIT","scripts": {
    "build": "webpack -p","serve:backend": "python manage.py runserver 4000","serve:frontend": "webpack-dev-server","seed": "python manage.py loaddata results/fixtures.json"
  },"dependencies": {
    "@babel/core": "^7.5.5","@babel/plugin-transform-runtime": "^7.6.0","@babel/preset-env": "^7.6.0","@babel/preset-react": "^7.0.0","@babel/runtime": "^7.6.0","@fortawesome/fontawesome-free": "^5.10.2","axios": "^0.19.0","babel-loader": "^8.0.6","bulma": "^0.7.5","copy-webpack-plugin": "^5.0.4","css-loader": "^3.2.0","file-loader": "^4.2.0","html-webpack-plugin": "^3.2.0","jsonwebtoken": "^8.5.1","moment": "^2.24.0","moment-duration-format": "^2.3.2","node-sass": "^4.12.0","react": "^16.9.0","react-dom": "^16.9.0","react-image": "^2.2.0","react-router-dom": "^5.0.1","react-select": "^3.0.4","react-select-async-paginate": "^0.3.13","react-toastify": "^5.4.0","sass-loader": "^7.3.1","style-loader": "^1.0.0","webpack": "^4.39.2","webpack-cli": "^3.3.7"
  },"devDependencies": {
    "babel-eslint": "^10.0.3","eslint": "^6.3.0","eslint-plugin-react": "^7.14.3","webpack-dev-server": "^3.8.0"
  },"engines": {
    "node": "12.11.1","python": "3.7.5"
  }
}

Settings.py

"""
Django settings for project project.

Generated by 'django-admin startproject' using Django 2.2.5.

For more information on this file,see
https://docs.djangoproject.com/en/2.2/topics/settings/

For the full list of settings and their values,see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
# import dj_database_url
from dotenv import load_dotenv
import django_heroku
load_dotenv()
# Build paths inside the project like this: os.path.join(BASE_DIR,...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/


SECRET_KEY = os.environ['SECRET_KEY']


# Security WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['0.0.0.0','localhost','pairshead-results.herokuapp.com']


# Application deFinition

INSTALLED_APPS = [
    'django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','corsheaders','rest_framework','results','django_filters','computed_property',]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','corsheaders.middleware.CorsMiddleware','django.middleware.common.CommonMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware',]

CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = [
    'http://localhost:3030',]
CORS_ORIGIN_REGEX_WHITELIST = [
    'http://localhost:3030',]

ROOT_URLconf = 'project.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates','Dirs': [],'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',],},]

Wsgi_APPLICATION = 'project.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3','NAME': os.path.join(BASE_DIR,'db.sqlite3'),}
}

# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',{
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',{
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',{
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',]


# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/

LANGUAGE_CODE = 'en-gb'

TIME_ZONE = 'Europe/London'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS,JavaScript,Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = '/static/'

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination','PAGE_SIZE': 25,'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',),'PAGE_SIZE_QUERY_ParaM': 'page_size','DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer','rest_framework.renderers.browsableAPIRenderer','DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication'
    ],}

django_heroku.settings(locals())
# DATABASES['default'] = dj_database_url.config(conn_max_age=600,ssl_require=True)

urls.py(来自项目文件夹)

from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('django-admin/',admin.site.urls),path('auth/',include('rest_framework.urls')),path('api/',include('results.urls')),include('jwt_auth.urls')),path('',include('frontend.urls')),]

wsgi.py

"""
Wsgi config for project project.

It exposes the Wsgi callable as a module-level variable named ``application``.

For more information on this file,see
https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE','project.settings')

application = get_wsgi_application()

urls.py

from django.urls import path
from .views import clubs
from .views import events
from .views import bands
from .views import crews
from .views import competitors
from .views import times
from .views import results
from .views import masters_adjustments
from .views import original_event_category


urlpatterns = [
path('clubs/',clubs.ClubListView.as_view()),path('club-data-import/',clubs.ClubDataimport.as_view()),path('events/',events.EventListView.as_view()),path('event-data-import/',events.EventDataimport.as_view()),path('band-data-import/',bands.BandDataimport.as_view()),path('bands/',bands.BandListView.as_view()),path('crews/',crews.CrewListView.as_view(),name='crews-list'),path('crews/<int:pk>',crews.CrewDetailView.as_view(),name='crews-detail'),crews.CrewListView.as_view()),path('results/',results.ResultsListView.as_view()),path('results-export/',results.ResultDataExport.as_view()),path('crew-update-rankings/',crews.CrewUpdaterankings.as_view()),path('crew-data-import/',crews.CrewDataimport.as_view()),path('crew-data-export/',crews.CrewDataExport.as_view()),path('competitor-data-export/',competitors.CompetitorDataExport.as_view()),path('competitor-data-import/',competitors.CompetitorDataimport.as_view()),path('race-times/',times.RaceTimeListView.as_view()),path('race-times/<int:pk>',times.RaceTimeDetailView.as_view()),path('crew-race-times/',times.CrewRaceTimesImport.as_view()),path('masters-adjustments-import/',masters_adjustments.MastersAdjustmentsImport.as_view()),path('original-event-import/',original_event_category.OriginalEventCategoryImport.as_view()),]

我有一个包含9个视图文件的views文件夹: 初始化 .py

from .bands import *
from .clubs import *
from .competitors import *
from .crews import *
from .events import *
from .times import *
from .results import *
from .masters_adjustments import *

procfile

web: python manage.py runserver 0.0.0.0:$PORT --noreload

非常感谢任何人都可以提供的帮助。在阅读了一些类似的问题之后,我尝试在webpack.config.js中设置{output:publicPath:'/'}和{historyApiFallback:true},但似乎没有任何作用。

解决方法

您的webpack和package.json配置绝对正确。您的特定MIME类型(“ text / html”)问题在您的Django配置中。

  1. React前端中的views.py在HttpResponse中需要一个content_type参数。
  2. Heroku需要知道Webpack构建文件的位置。

您已经将Webpack配置为编译React应用的生产版本,并将其命名为“ bundle.js”,并告诉Webpack将其与索引的生产版本一起放入名为“ frontend / dist”的文件夹中。 html。用Django的话来说,这些是您的“静态”文件。 (如果使用的是create-react-app而不是Webpack,则这是'build'文件夹中的内容。)在settings.py中,您需要告诉heroku在哪里可以找到这些“静态”文件。 (如下所述)。但首先,请修复您的frontend / views.py。

您的Home(View)告诉Heroku(或任何服务器)通过发送index.html进行响应。您的Webpack'HTMLWebpackPlugin'已将脚本注入index.html,要求您的Assets(View):查找bundle.js(以及服务器上同一文件夹中存储的所有其他文件),将其打开为'rb', (代表“读取二进制”),并将其作为HttpResponse返回给用户。

您的“拒绝执行脚本... MIME类型('text / html')”问题源自Django的HttpResponse默认content_type设置,即text/htmlhttps://docs.djangoproject.com/en/3.1/ref/request-response/#id3

通过在content_type='application/javascript'的return语句中包含Assets(View)自变量来解决此问题,如下所示:

class Assets(View):

    def get(self,_request,filename):
        path = os.path.join(os.path.dirname(__file__),'dist',filename)

        if os.path.isfile(path):
            with open(path,'rb') as file:
                return HttpResponse(file.read(),content_type='application/javascript')
        else:
            return HttpResponseNotFound()

排序后,您需要对settings.py文件进行一些更改,以帮助Heroku的Django配置正确提供这些文件。

顺便说一句,Heroku的Django部署过程建议安装一个中间件软件包(“ Whitenoise”)以压缩和管理您的静态文件,并安装一个wsgi界面(“ Gunicorn”)以帮助Heroku与Django通信。缺少这些并不是造成问题的原因,但是它们是Heroku当前建议的配置的一部分,因此我将它们包括在下面。

首先,在settings.py中,您需要在允许的主机中包括heroku应用程序的地址,以及端口和本地主机的地址,如下所示:

ALLOWED_HOSTS = ['your-app-name.herokuapp.com/','127.0.0.1','localhost']

然后,您需要添加whitenoise中间件(别忘了pip安装它。)确保在django的安全中间件之后紧随其后列出它:

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware','whitenoise.middleware.WhiteNoiseMiddleware','django.contrib.sessions.middleware.SessionMiddleware',... 

然后,您需要将Webpack将资产存储到DIRS的路径添加到DIRS中(在您的情况下为frontend / dist):

TEMPLATES = [
{
    'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [os.path.join(BASE_DIR,'frontend/dist')],'APP_DIRS': True,...

最后,也是最重要的是,您需要配置存储静态文件的位置。就您而言:

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR,'staticfiles')
STATICFILES_STORAGE = 
"whitenoise.storage.CompressedManifestStaticFilesStorage"
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'frontend/dist')
]

同时设置STATIC_ROOT和STATICFILES_DIRS的原因是,在部署期间Heroku自动调用命令manage.py collectstatic时,将在STATIC_ROOT收集所有静态文件。

STATICFILES_DIRS用于包含其他要收集的静态目录。确保您引用了Webpack正确存储构建文件的文件夹的路径!对于您的特定目录设置,应为“ frontend / dist”

不要忘记将DEBUG设置更改为False进行部署。

最后,您需要pip安装gunicorn并将Procfile更改为如下所示:

release: python manage.py migrate
web: gunicorn project.wsgi --preload --log-file -

您应该真正检查一下Heroku链接:https://blog.heroku.com/from-project-to-productionized-python,因为它会引导您完成Heroku和Heroku的环境设置。它还指出,Heroku需要一个指定您已安装的python软件包版本的requirements.txt文件和一个指定您的Django版本的runtime.txt文件。但是,但是由于您使用的是Pipenv而不是venv,所以我认为您的Pipfile使得这些不必要。

以下是Heroku从Django到Heroku的从产品到生产的完整说明的大纲,并包括按正确顺序插入React + Webpack前端的必要步骤: --------预部署-------------

  1. 注册Heroku
  2. 安装Heroku CLI
  3. 使用pipenv shell或venv https://docs.python.org/3/tutorial/venv.html设置虚拟环境
  4. 更新.gitignore以包括:
/your-venv-directory      
__pycache__
db.sqlite3         
your-app-name/static/
frontend/dist
.env
  1. [Heroku建议您使用settings.py进行本地开发,并使用django-environ包创建另一个文件(heroku.py),以导入您的环境设置以进行部署。他们的方法要容易得多,但是您可以通过env config很好地进行管理,因此在此我将跳过它。检查modularize-your-settingssetting-up-code-heroku-py以获得推荐的设置]
  2. 安装django-heroku并添加 import django_heroku 到settings.py文件的顶部,然后 django_heroku.settings(locals()) 到settings.py文件的底部
  3. 安装whitenoise并将其作为中间件添加到settings.py
  4. 安装psycopg2 http://initd.org/psycopg/docs/ 众所周知,这很难安装,但像您在此处那样安装原始psycopg2-binary似乎很容易。
  5. 创建一个requirements.txt文件,然后运行pip freeze > requirements.txt并创建一个runtime.txt文件,并指定您当前的python构建版本,以免麻烦。当您使用pipenv生成Pipfile.lock时,我不确定这是绝对必要的,因为pipenv会取代,但您应该将当前的程序包和python构建版本冻结到Pipfile中,以免发生麻烦。
  6. 安装实际为您的heroku应用程序提供服务的Web服务器网关接口(WSGI)流程:gunicorn https://devcenter.heroku.com/articles/python-gunicorn https://docs.gunicorn.org/en/latest/settings.html
  7. 创建一个名为Procfile的文件(确保大写的“ P”!)并添加:
    release: python manage.py migrate
    web: gunicorn gettingstarted.wsgi --preload --log-file -
  1. 确保您的package.json中有一个构建脚本
"scripts": {
  "build": "webpack -p" }
  1. 运行此构建脚本(yarn build)并确认您的应用在本地运行。

--------部署------------------ 从终端运行:

  1. heroku login
  2. heroku create --region=eu your-app-name
  3. heroku buildpacks:add heroku/nodejs
  4. heroku buildpacks:add heroku/python(确保以该顺序添加构建包!)
  5. heroku config:set ALLOWED_HOSTS=your-app-name.herokuapp.com
  6. heroku config:set DJANGO_SETTINGS_MODULE=project.settings(如果您添加了部署设置文件以使用django-environ作为上面建议的模块化您的设置链接,请使用heroku config:set DJANGO_SETTINGS_MODULE=project.settings.herokuDotPyOrWhateverYouNamedIt
  7. heroku config:set SECRET_KEY=INSERTASECURESECRETKEYPASSWORD
  8. heroku config:set WEB_CONCURRENCY=1
  9. heroku addons:create heroku-postgresql:hobby-dev
  10. 确保您位于master分支上,并且所有更改都已提交给git并运行 git push heroku master
    或者如果您正在另一个分支中工作,则提交到git并运行 git push heroku yourbranch:master用分支名称替换“ yourbranch”。
  11. heroku run python manage.py migrate
  12. 如果您有一个包含数据库种子运行的Fixtures.json文件 heroku运行python manage.py loaddata your-django-project-name / fixtures.json
  13. heroku ps:scale web=1
  14. heroku open
  15. 如果有任何错误,请运行 heroku logs --tail 调查

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。