VueJS dev работает с обратным прокси

Исходная статья доступна по адресу: https://medium.com/homullus/vuejs-dev-serve-with-reverse-proxy-cdc3c9756aeb

В статью добавлена ​​ОЧЕНЬ упрощенная настройка благодаря волшебной науке изучения исходного кода. Вы можете найти его внизу.

Я столкнулся с глупой проблемой, когда настраивал новый проект для своих товарищей по команде. Проект является открытым исходным кодом погоды / одежды, и если это мало что объясняет, просто посетите репо или веб-сайт: http://kaputtweather.com



Настройка VueJS

VueJS в 2019 имеет довольно процесс настройки: вы используете команду cli для загрузки нового проекта в определенную папку со всеми необходимыми зависимостями. Это мило, и это действительно хорошо работает, особенно для молодых разработчиков, которые не сильно увлекаются системным администратором в нашей работе. : D

Он буквально порождает собственный интерфейс, и я не шучу. Говорите о бесполезных накладных расходах вместо того, чтобы вкладывать усилия в качество.

В любом случае, вы просто создаете проект, а затем запускаете вездесущий yarn serve или yarn build. Проблема прямо здесь, просто вы ее еще не видите.

Нет часов ...

Да, кто-то решил, что часы никому не нужны, и что если они будут существовать, они будут обернуты в пакет / сервер / наблюдатель / клиент HMR собственного изготовления (потому что зачем кому-то запускать собственный сервер, это просто глупо , все нужно писать на JS и еще нахрен стандарты). Я предполагаю, что где-то есть проблема с GitHub, в которой говорится что-то вроде:

Бу. Мы не хотим ждать 500 мс опроса, как крестьяне, давайте сделаем наш собственный сервер и нашу собственную систему наблюдения.

Команда serve была создана таким образом, что она порождает собственный локальный сервер Vue на порту 8080 и не создает никаких видимых файлов (все файлы создаются во время выполнения). Если вы хотите воспользоваться преимуществами HMR или даже автоматической перезагрузки, вам придется использовать их сервер. Я ничего не имею против, но если вы собираетесь ограничивать нас таким образом, вы должны создавать гибкие флаги командной строки, чего не сделали. Это глупо, поскольку нет двух одинаковых настроек инфраструктуры и у них нет одинаковых потребностей. Но я думаю, это то, что вы получаете, используя удобный для новичков инструмент для якобы простой задачи.

В любом случае, моя установка потребовала, чтобы я работал через Nginx как в разработке, так и в продукте, поэтому я сделал следующее:

  1. Разделение целей конфигурации сервера dev / prod в моем Dockerfile. (лучше объясню в следующем посте) (tldr; используйте немного другой .conf для настройки nginx на dev.)
  2. Конфигурация Dev не будет использовать блок / по умолчанию, который обычно указывает на папку build / dist, а вместо этого будет определять прокси для сервера узла в другом контейнере.

1. простой прокси Nginx

- Хорошо, мы можем это решить, - сказал я. Мы постоянно запрашиваем проксирование с помощью серверных микросервисов. По этому поводу есть даже набор неписаных правил. Это довольно распространенная практика с бэкэнд-технологиями:

location / {
    proxy_pass  http://localhost:8080/;
    proxy_set_header    Host                $host;
    proxy_set_header    X-Real-IP           $remote_addr;
    proxy_set_header    X-Forwarded-Host    $host;
    proxy_set_header    X-Forwarded-Server  $host;
    proxy_set_header    X-Forwarded-Proto   $scheme;
    proxy_set_header    X-Forwarded-For     $remote_addr;
    proxy_redirect off;
    proxy_connect_timeout 90s;
    proxy_read_timeout 90s;
    proxy_send_timeout 90s;
}

Это запустит мой Nginx, как обычно, со всеми другими серверами и блоками, но будет проксировать все запросы, которые попадают в этот конкретный блок, через Nginx и на сервер Vue, найденный по адресу localhost: 8080. Итак, с точки зрения Vue, он действительно работает в корне домена kaputtweather.com.

Вы можете найти похожий пример здесь:



2. Недействительный заголовок хоста.

Мне не потребовалось много времени, чтобы понять, что это не сработает. По какой-то еще более глупой причине ребята из Webpack-dev-server, похоже, заблокировали всех в использовании localhost (или установили флаг serve cli) .- что за херня?

location / {
    proxy_pass  http://localhost:8080/;
    proxy_set_header    Host                localhost;
    proxy_set_header    X-Real-IP           $remote_addr;
    proxy_set_header    X-Forwarded-Host    localhost;
    proxy_set_header    X-Forwarded-Server  localhost;
    proxy_set_header    X-Forwarded-Proto   $scheme;
    proxy_set_header    X-Forwarded-For     $remote_addr;
    proxy_redirect off;
    proxy_connect_timeout 90s;
    proxy_read_timeout 90s;
    proxy_send_timeout 90s;
}

Что мы обычно делаем на бэкэнде, так это то, что наши приложения следят за заголовками X-Forwarded-Host (и аналогичными), которые можно жестко запрограммировать в nginx. Просто поменяйте местами все ссылки на хост и жестко закодируйте их на localhost. Сервер Vue начнет думать, что мы используем его в домене localhost, и разрешит доступ. Ура.

3. Замена розеток и горячего модуля

HMR сначала не работал. По крайней мере, он пытался работать. Но он не мог передать запрос «Обновление соединения» на сервер NodeJS. Заметил это случайно, в сетевой консоли Chrome. Мы просто определяем классный новый маленький блок, специфичный для Sockets ...

location /sockjs-node/ {
    proxy_pass http://localhost:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
# And now all the stuff from above, again.
proxy_set_header    Host                localhost;
    proxy_set_header    X-Real-IP           $remote_addr;
    proxy_set_header    X-Forwarded-Host    localhost;
    proxy_set_header    X-Forwarded-Server  localhost;
    proxy_set_header    X-Forwarded-Proto   $scheme;
    proxy_set_header    X-Forwarded-For     $remote_addr;
    proxy_redirect off;
    proxy_connect_timeout 90s;
    proxy_read_timeout 90s;
    proxy_send_timeout 90s;
}

Излишне говорить, что это следует использовать только в среде разработки, если вы хотите использовать его в продукте, я бы предложил вместо этого правильно изучить конфигурацию Webpack. Если вам нужна дополнительная информация, я бы посоветовал прочитать это:



Замечание о CORS и CORB на прокси-сервере Nginx

В обычных обстоятельствах сам сервер будет использовать предоставленный источник для CORS / B. Но поскольку мы переопределяем это с помощью localhost, мы возвращаем заголовок CORS, который разрешает запросы только к домену localhost.

proxy_hide_header Access-Control-Allow-Origin;
add_header Access-Control-Allow-Origin "http://kaputtweather.com";

Добавляя это в наш серверный блок, мы удаляем заголовок, полученный от прокси, и заменяем его нашим собственным жестко заданным доменным именем.

Заголовок хоста + HMR: ОБНОВЛЕНИЕ (28.09.2019)

Я подумал, что что-то не так, поскольку настройка была немного шаткой, и у нас было довольно много сброшенных запросов ajax. Также HMR не работал должным образом (каждый второй запрос завершался ошибкой), что было головной болью, но я этого не заметил на момент написания.

Я почувствовал какое-то нестандартное поведение, характерное для экосистемы JS, поэтому перешел на серверный код Webpack Dev. Как вы можете заметить, кто-то знал о стандартном использовании, но не позаботился о том, чтобы охватить все варианты использования. Они проверяли только заголовок Origin (который, кстати, обычно не используется для этого типа вещей). Это немного упрощает нашу настройку. Если WebpackDevServer все равно не смотрит на все стандартные заголовки, я могу просто убить их:

location / {
    proxy_pass  http://kaputt_node:8080/;
    proxy_set_header Host localhost;
    proxy_set_header Origin localhost;
    proxy_hide_header Access-Control-Allow-Origin;
    add_header Access-Control-Allow-Origin "http://kaputtweather.com";
}

location /sockjs-node/ {
    proxy_pass http://kaputt_node:8080;
    proxy_set_header Host localhost;
    proxy_set_header Origin localhost;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_hide_header Access-Control-Allow-Origin;
    add_header Access-Control-Allow-Origin "http://kaputtweather.com";
}

Наш сервер теперь все еще думает, что он запущен с localhost. Розетки тоже.

Вы можете увидеть полный файл conf в репозитории GitHub: