部署在 Apache2 系统上的 Dash 应用程序永远不会让用户超过 'Loading...',因为它似乎找不到它的 dash .js 文件

Dash app deployed on an Apache2 system never lets user past 'Loading...' because it cannot seem to find its dash .js files

我正在尝试使用 Apache2 服务器和 mod_wsgi 为 (python3.8.2) dash 应用程序提供服务,但该应用程序在“正在加载...”屏幕上停止。每个 dash 的 .js 脚本的服务器 returns 404s。我在使用 dash 的内置本地服务器时没有遇到任何问题......但我并没有尝试在本地提供服务。

我希望得到一些关于我哪里出错的建议,以及如何启动和 运行ning 的这个特定应用程序。

症状

我能够使用我的设置同时提供一个简单的 python“hello world”和一个简单的 flask 应用程序。但是,在创建一个简单的 'dash' 应用程序时...

[Error] Failed to load resource: the server responded with a status of 404 (Not Found) (polyfill@7.v1_6_0m1598005008.8.7.min.js, line 0)
... followed by 12 more similar error messages...
[Error] Failed to load resource: the server responded with a status of 404 (Not Found) (dash_renderer.v1_6_0m1598005008.min.js, line 0)
[Error] ReferenceError: Can't find variable: DashRenderer
    Global Code (hazcurves:28:103)

我的 apache 访问日志显示了一系列得到 404 的 GET 请求(这里是一个例子):

... "GET /_dash-component-suites/dash_renderer/dash_renderer.v1_6_0m1598005008.min.js HTTP/1.1" 404 495 "http://efehr-dev.ethz.ch/hazcurves/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Safari/605.1.15"

补充观察

当我将我提供的 html 与正常运行的 Dash 应用程序提供的 html 进行比较时,我注意到 .js 名称有所不同。看来我的不知何故被破坏了。

功能版本,来自https://dash-gallery.plotly.host/dash-wind-streaming/

# Excerpt from functioning app's "footer" section
<footer>
  <script id="_dash-config" type="application/json">{"url_base_pathname": null, "requests_pathname_prefix": "/dash-wind-streaming/", "ui": false, "props_check": false, "show_undo_redo": false}</script>

  # [CGR] then there are  several components here that are variations of the following
  <script src="/dash-wind-streaming/_dash-component-suites/dash_renderer/dash_renderer.min.js?v=1.0.0&m=1583853516"></script>

  <script id="_dash-renderer" type="application/javascript">
        var renderer = new DashRenderer();
        </script>

我的应用程序的页脚使请求看起来杂乱无章,查询参数被吸收到文件名中。

<footer>
  <script id="_dash-config" type="application/json">{"url_base_pathname": null, "requests_pathname_prefix": "/", "ui": false, "props_check": false, "show_undo_redo": false, "suppress_callback_exceptions": false, "update_title": "Updating..."}</script>
   
  # [CGR] then there are  several components here that are variations of the following
  <script src="/_dash-component-suites/dash_html_components/dash_html_components.v1_0_3m1598005008.min.js"></script>
  <script src="/_dash-component-suites/dash_renderer/dash_renderer.v1_6_0m1598005008.min.js"></script>
  <script id="_dash-renderer" type="application/javascript">var renderer = new DashRenderer();</script>
        </footer>

现在,这些 .js 文件 [未加密版本] 确实存在,并且 _dash-component-suites 似乎映射到我的 .local/lib/python3.8/site-packages 文件夹。

因此,根据我上面显示的内容,我有 .../dash_renderer/dash_renderer.min.js.../dash_html_components.min.js

我的系统:

一个干净的系统 Ubuntu 20.04.1 LTS,安装了 mod_wsgi Apache 2.4。
Python 3.8.2 安装了以下相关包 [using sudo pip3] :

dash==1.14.0
dash-core-components==1.10.2
dash-html-components==1.0.3
dash-renderer==1.6.0
dash-table==4.9.0
Flask==1.1.2
Flask-Compres=1.5.0

这是我的 app.wsgi:

from flask import Flask
server = Flask(__name__)

import dash
import dash_core_components as dcc
import dash_html_components as html
app = dash.Dash(server=server) 
app.css.config.serve_locally = True  
app.scripts.config.serve_locally = True
app.layout = html.Div(children=["hello"])
application = app.server

我已经能够 运行 使用内置服务器,在本地服务器上提供它。

我的站点配置文件:

<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        DocumentRoot /home/username/public_html

        WSGIDaemonProcess /home/username/public_html/myapp.wsgi processes=2 threads=15 display-name=%{GROUP}
        WSGIScriptAlias /hazcurves /home/username/public_html/myapp.wsgi

        <Directory /home/username/public_html>
                AllowOverride all
                Options Indexes FollowSymLinks
                <Limit GET POST OPTIONS>
                        Require all granted
                </Limit>
        </Directory>


        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

我承认尝试过的一些事情

在尝试从与这个问题无关的网站上强行提出建议后,我开始觉得自己像一只敲击键盘的猴子 --- 感觉,嗯 错误 (而且不安全)

最后警告:这是我第一次尝试在服务器端管理应用程序。

我很高兴地报告我最终弄明白了,而且我的应用程序现在 运行 很棒。这是我学到的。

我在调用 dash.Dash(...) 时必须注意以下几点,而不是我写的,我需要:

dash.Dash(__name__, requests_pathname_prefix='/hazcurves/')

重要的教训如下:

  1. 不要覆盖服务器变量。不知何故,我丢失了我创建的所有配置。
  2. requests_pathname_prefix 需要匹配 URL 别名(开始结束以斜杠结束)。

红鲱鱼(实际上无关紧要的事情):

  1. 首先创建一个 Flask 实例
  2. 关于本地服务的配置
app.css.config.serve_locally = True  
app.scripts.config.serve_locally = True

因此,以下是我感兴趣的三个文件的摘录:

mysite.conf : /etc/apache2/sites-available/mysite.conf

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot /home/myusername/public_html


    # ---- Hazard Curves App ---- #
    # using WSGIProcessGroup within Location allows multiple apps to run
    # without interfering with each other

    WSGIDaemonProcess curves/wsgi.py processes=2 threads=15 display-name=%{GROUP}
    WSGIScriptAlias /curves /home/myusername/public_html/curves/wsgi.py
    <Location /curves>
        WSGIProcessGroup curves/wsgi.py
    </Location>
</VirtualHost>

wsgi.py : ~/public_html/curves/wsgi.py

#!/usr/bin/python3

from myapp import app
application = app.server

myapp.py : ~/public_html/curves/myapp.py

import dash
import dash_html_components as html

app = dash.Dash(__name__, requests_pathname_prefix='/curves/')

app.title = "Some Test"
app.layout = html.Div([html.H6("Hello World")])

if __name__ == '__main__':
    app.run_server(port=8051, debug=True) # unimportant in this context