Я пытаюсь развернуть веб-приложение, созданное с помощью Django / Redux / React / Webpack, на капле Digital Ocean. Я использую Phusion Passenger и Nginx на сервере развертывания.
Я использовал create-response-app для создания приложения Django, у которого есть интерфейс, использующий React / Redux, и бэкэнд api, использующий django-rest-framework. Я построил интерфейс с помощью npm run build.
Приложение Django настроено на поиск файлов в папке frontend / build, и все работает как положено, включая аутентификацию. Он основан на этом руководстве: http://v1k45.com/blog/modern-django-part-1-setting-up-django-and-react/
В settings.py:
ALLOWED_HOSTS = ['*']
TEMPLATES = [
...
'DIRS': [
os.path.join(BASE_DIR, 'frontend/build'),
],
...
]
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'frontend/build/static'),
]
На своей машине разработки я активирую виртуальную среду Python 3.6 и запускаю ./manage.py runserver, и приложение отображается по адресу localhost: 3000.
На сервере развертывания я клонировал файлы в папку в var / www / и построил интерфейс.
Я настроил Passenger в соответствии с документами с помощью файла passenger_wsgi.py:
import myapp.wsgi
application = myapp.wsgi.application
И файл wsgi.py находится в папке djangoapp ниже:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myapp.settings')
application = get_wsgi_application()
Документация по Passenger распространяется только на приложение, состоящее из одной части:
https://www.phusionpassenger.com/library/walkthroughs/start/python.htmlhttps://www.phusionpassenger.com/library/walkthroughs/deploy/python/digital_ocean/nginx/oss/xenial/deploy_app.htmlhttps://www.phusionpassenger.com/library/deploy/wsgi_spec.html
Я пробовал клонировать код учебной части 1 прямо на свой сервер и, следуя инструкциям, запустить его. Я заставил это работать на сервере, добавив "proxy": "http://localhost:8000" в frontend / package.json. Если я запускаю сервер Django с ./manage.py runserver --settings=ponynote.production_settings xxx.x.x.x:8000
, тогда приложение правильно обслуживается на моем сервере: 8000. Однако Passenger по-прежнему не обслуживает нужные файлы.
Я изменил wsgi.py, чтобы сказать следующее:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.production_settings")
application = get_wsgi_application()
Страница, обслуживаемая Passenger в корневом URL-адресе, теперь имеет правильные ссылки на файлы js, такие как "text / javascript" src = "/ static / bundles / js / main.a416835a.js, но ссылки не работают: ожидаемого js нет. Passenger не обслуживает файлы js из static / bundles / js, хотя сервер Django может их найти.
Очень благодарен за любую помощь или идеи.
Django находится в нужном месте на сервере разработки, так разве это не значит, что он находится в нужном месте и на рабочем сервере? Расположение в settings.py является относительным и должно быть одинаково правильным в производственной среде.
В качестве ответа я опубликовал более полное объяснение - сложно точно определить причину, по которой приложение React не отображается, но приведенный ниже ответ должен дать общее представление о том, почему в руководстве, которому вы следуете, рекомендуется делать то, что они делают.






Приложение Create-react-app имеет довольно оптимистичную настройку для локальных и производственных сред.
Локально при запуске npm start будет запущен webpack-dev-сервер, к которому вы обычно обращаетесь через порт 3000. Он запускает локальный веб-сервер nodejs для обслуживания файлов. Вы можете направлять запросы на локальный сервер Django с помощью параметра доверенное лицо.
Стоит отметить, что на данный момент связь между вашим приложением React и Django практически отсутствует. Если вы используете настройку прокси, единственное, что связывает два приложения, - это маршрутизация любых запросов, не обрабатываемых вашим приложением React, в ваше приложение Django через порт.
По умолчанию в приложении create-response-app (и, как указано в руководстве, которое вы упомянули, вы следуете), в производстве вы должны запустить npm run build, который преобразует ваши файлы приложения create-response-app в статические файлы JS и CSS, которые затем доступны в Django. как статические файлы любое другое приложение Django.
Одна вещь, которую Django не хватает для доступа к статическим файлам, - это способ узнать, какие файлы создаются при запуске npm run build. Запуск сборки обычно приводит к выходным файлам, подобным этому:
- css
|- main.e0c3cfcb.css
|- main.e0c3cfcb.css.map
- js
|- 0.eb5a2873.chunk.js
|- 0.eb5a2873.chunk.js.map
|- 1.951bae33.chunk.js
|- 1.951bae33.chunk.js.map
К именам файлов добавляется случайный хэш, чтобы гарантировать очистка кеша. Здесь на помощь приходят веб-пакет-трекер и django-webpack-загрузчик. При создании файлов сборки также создается сопутствующий файл с именем manifest.json, в котором перечислены файлы, созданные для сборки. Он генерируется в Webpack и подбирается django-webpack-loader, чтобы Django мог знать, какие файлы импортировать.
Можно запустить сервер nodejs в производстве или использовать рендеринг на стороне сервера, но если вы следуете упомянутому вами руководству и используете настройки по умолчанию для create-response-app, то запуск npm run build и развертывание статических файлов - самый простой и безопасный вариант. .
Ничто в упомянутых вами ссылках развертывания Passenger не касается чего-либо, кроме развертывания приложения Python / Django - вам нужно будет управлять двумя приложениями и развертываниями, чтобы и Django, и React работали как серверы в производственной среде.
Обратите внимание, что в указанном вами руководстве рассказывается, как загрузить файлы сборки в Django в производственной среде, но вам необходимо убедиться, что у вас есть веб-пакет-трекер, django-webpack-загрузчик и конфигурация статических файлов Django, настроенная для совместной работы.
Спасибо за ваше объяснение. Я считаю, что следую именно тому процессу, который вы предлагаете - я запустил npm run build на производственной машине, - но я не могу понять, почему статические файлы не обнаруживаются на производственном сервере. Они присутствуют в указанной папке, и я не изменил конфигурацию того, что работает на машине разработки, где я определенно нет запускает отдельное приложение для клиента, только основное приложение Django, которое находит статические файлы и обслужить их без проблем. В настоящее время я не могу думать, как исследовать это дальше.
В браузере я вижу, что приложение загрузило два файла: build / static / js / 1.ab5b0163.chunk.js и build / static / js / main.53d060d0.chunk.js. Однако содержимое выглядит неправильно, каждое из них - это просто html. Соответствующие файлы, созданные на моей машине для разработки, содержат много сжатого JavaScript. Итак, я думаю, что с моим процессом сборки что-то не так.
какой HTML в этих файлах?
Спасибо, к основному вопросу я добавил HTML. Следующее, что я могу придумать, - это создать приложение полностью на производственном сервере, чтобы посмотреть, работает ли оно.
Я настоятельно рекомендую создавать файлы локально и развертывать их для работы с остальной частью приложения Django. Я не уверен, почему файл js, созданный на сервере, включает HTML и всю кодовую базу, но это, очевидно, неправильно.
Это похоже на гораздо лучший план. Я новичок в Django и не знаю, как правильно развернуть его в prod - я привык к Meteor, где вы просто создаете пакет и распаковываете его на сервере. Вы можете порекомендовать метод? Например. мне добавить файлы сборки в GitHub? Или есть хороший инструмент для прямого копирования приложения с локального на прод?
Я скопировал файлы build / static с моего локального компьютера на сервер и открыл 1.xxx.chunk.js, чтобы убедиться, что он имеет то же содержимое, что и локальный файл. Однако браузер по-прежнему видит неправильный контент, который на самом деле является общедоступным файлом index.html, и я сделал жесткую перезагрузку. Кажется, что сервер обслуживает public / index.html вместо всех моих статических файлов?
файл index.html из приложения create-response-app не используется в производстве - в prod у вас будет шаблон Django, который должен иметь ссылку внизу на файлы, созданные Webpack (через django-webpack-loader). Вы можете проверить файлы в GitHub, но если вы работаете с другими, они будут постоянным источником конфликтов слияния. В настоящее время моя команда использует Docker для управления средами и развертываниями.
Позвольте нам продолжить обсуждение в чате.
Ключевым отсутствующим параметром был параметр «местоположение» в конфигурационном файле Passenger.
Хотя сервер Django обслуживает статические файлы, включая файлы сборки для вашего приложения React, Nginx не видит никаких статических файлов, кроме тех, что находятся в «общедоступном» каталоге.
Итак, чтобы развернуть приложение Django, созданное с помощью Webpack, в рабочей среде, вам необходимо сообщить Nginx об этих файлах. Если вы используете Passenger, эти настройки, вероятно, находятся в отдельном файле конфигурации Passenger. «alias» - это команда, которую следует использовать в том случае, когда имя папки отличается от «static» (на которое указывают ссылки веб-страницы).
Если вы используете виртуальную среду для своего приложения, вам необходимо указать, где Passenger может найти нужный исполняемый файл Python.
/etc/nginx/sites-enabled/myapp.conf
server {
listen 80;
server_name xx.xx.xx.xx;
# Tell Passenger where the Python executable is
passenger_python /var/www/myapp/venv36/bin/python3.6;
# Tell Nginx and Passenger where your app's 'public' directory is
# And where to find wsgi.py file
root /var/www/myapp/myapp/myapp;
# Tell Nginx where Webpack puts the bundle folder
location /static/ {
autoindex on;
alias /var/www/myapp/myapp/assets/;
}
# Turn on Passenger
passenger_enabled on;
}
Passenger использует файл wsgi.py как точку входа в ваше приложение. Вам нужен файл пассажира_wsgi.py на один уровень выше файла wsgi.py. Это сообщает Пассажиру, где найти файл wsgi.py.
/var/www/myapp/myapp/passenger_wsgi.py
import myapp.wsgi
application = myapp.wsgi.application
/var/www/myapp/myapp/myapp/wsgi.py
Если вы используете отдельный файл production_settings.py, убедитесь, что он указан здесь.
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.production_settings")
application = get_wsgi_application()
Обычно файлы внешнего интерфейса создаются (в приложении create-response это делается при запуске
npm run build), а затем включаются в Django через рабочий процесс staticfiles. Я прошел через это и обнаружил, что конфигурация django-webpack-loader немного неудобна - вам нужно убедиться, что после создания ваших файлов django ищет файл manifest.json и статические файлы в нужном месте.