Посещение страницы индекса или / pages / _id страниц У меня нет ошибок.Но когда я пытаюсь открыть / другую страницу, она вылетает.
Чтобы переформулировать:
- У меня есть главная страница на
/
, которая показывает некоторые ссылки, нацеленные на страницы в/pages/_id
(где _id
- действительный идентификатор игры) - Когда я открываю
/
или /pages/_id
, содержимое отображается - Но если я нажимаю ссылку со страницы
/
таргетинг /pages/xxx
(где xxx
- действительный идентификатор), я получил ошибку - Кроме того, если я обновляю страницу, я вижу содержимое, а не сообщение об ошибке
- .для этих страниц приходит с сервера API.Страницы должны извлекать содержимое, вызывая сервер API, а затем отображать содержимое страницы с ответом.
Что здесь происходит?
AsyncData
Способ asyncData работает в nuxt.js следующим образом:
при загрузке первой страницы
- пользователь вводит URL
http://yourserver/pages/123
в своем браузере - веб-сервер nuxt обрабатывает запрос, разрешает маршрут и монтирует компонент vue для этой страницы
- метод
asyncData
из компонента vue вызывается со стороны сервера nuxt.js - сервер nuxt.js (не пользовательский браузер) затем извлекает контент, совершая другой вызов
http://api:1337/games/123
, получает ответ и контент отображает.
когда пользователь нажимает на ссылку для другой страницы
Сейчас происходит что-то немного другое.
- Пользователь по-прежнему находится на странице
http://api:1337/games/123
, на которой есть ссылка на главную страницу со списком всех игр (http://yourserver/
) и щелкните ее. - theбраузер не загружает новую страницу .Вместо этого пользовательский браузер выполняет ajax-вызов
http://api:1337/games
, чтобы попытаться получить новый контент.И происходит сбой из-за ошибки разрешения имени
Почему?
Эта функция предоставлена nuxt.js для ускорения загрузки контента страницы.из документации важный бит информации:
asyncData
вызывается каждый раз перед загрузкой компонента страницы.Он будет вызываться на стороне сервера один раз (при первом запросе к приложению Nuxt) и на стороне клиента при переходе к следующим маршрутам.
server-side
означает, что вызов сделан изNUXT сервер к серверу API client-side
означает, что вызов сделан из браузера пользователя на сервер API
Теперь самое интересное:
- сервер nuxt работает в первом контейнере
- сервер API работает во втором контейнере и прослушивает порт
1337
- из контейнера nuxt, URL для вызова APIсервер
http://api:1337/
, и это нормально работает - из браузера пользователя, вызов
http://api:1337
завершается неудачно (net::ERR_NAME_NOT_RESOLVED
), потому что компьютер пользователя не знает, как преобразовать имя домена api
в IPадрес.И даже если бы это было возможно, этот IP-адрес был бы недоступен в любом случае.
Что можно сделать?
- Вам необходимо настроить обратный прокси-сервер, который будет пересылать запросы, сделанныебраузерами пользователей URL, начинающиеся с
http://yourserver/api/
в контейнер api
на порту 1337
. - И вам нужно настроить nuxt.js так, чтобы ссылки на API делали
client-side
(изпользовательский браузер) используйте URL http://yourserver/api
вместо http://api:1337/
- И вам нужно настроить nuxt.js так, чтобы он продолжал вызывать
http://api:1337
для вызовов server-side
.
добавление обратного прокси-сервера для вызовов из nuxt (server-side
)
Поскольку вы используете модуль Axios *1123* nuxt.js для выполнения вызовов в контейнер API, вы наполовину
Модуль Axios имеет опцию proxy , которую можно установить на true
в nuxtjs.config.js
Ниже приведен пример настройкиобратный прокси для вашего проекта, использующий Traefik , но в документации указано, что прокси несовместимс использованием опции baseURL .Вместо этого следует использовать параметр prefix .
Ваш nuxt.config.js должен выглядеть следующим образом:
axios: {
prefix: '/api',
proxy: true
},
proxy: {
'/api/': {
target: 'http://localhost:1337',
pathRewrite: {
'^/api/': ''
}
}
},
Это прекрасно работает с вашего компьютера разработки, где, если strapi работает и отвечает на http://localhost:1337
. Но это не сработает в контейнере, потому что нам нужно заменить http://localhost:1337
на http://api:1337
.
Для этого мы можем ввести переменную окружения (STRAPI_URL
):
axios: {
prefix: '/api',
proxy: true
},
proxy: {
'/api/': {
target: process.env.STRAPI_URL || 'http://localhost:1337',
pathRewrite: {
'^/api/': ''
}
}
},
Позже мы установим STRAPI_URL
в файле docker-compose.yml.
добавление обратного прокси для звонков, сделанных из браузера пользователя (client-side
)
Поскольку я отказался от реализации обратных прокси с nginx при использовании docker, вот пример с Traefik :
докер-compose.yml:
version: '3'
services:
reverseproxy: # see https://docs.traefik.io/#the-traefik-quickstart-using-docker
image: traefik
command: --docker
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
api:
image: strapi/strapi
environment:
- ...
expose:
- 1337
labels:
traefik.frontend.rule: PathPrefixStrip:/api
traefik.port: 1337
nuxt:
image: ...
expose:
- 3000
command:
"npm run start"
labels:
traefik.frontend.rule: PathPrefixStrip:/
traefik.port: 3000
Теперь все HTTP-запросы, сделанные браузером пользователя на http://yourserver
, будут обрабатываться обратным прокси-сервером Traefik.
Traefik настроит правила пересылки, просматривая метки, начинающиеся с traefik.
на контейнерах nuxt
и api
.
Что изменилось?
Теперь у вас есть 2 обратных прокси:
- один для
server-side
запросов (прокси-модуль nuxt.js )
- один для
client-side
запросов (Traefik)
Это еще не сделано
Теперь нам нужно проинструктировать прокси-модуль nuxt.js , что он должен пересылать запросы на http://api:1337/
. Для этого мы будем использовать переменную окружения STRAPI_URL
.
И нам нужно указать nuxt модуль Axios , что браузер пользователя должен вызвать API на http://yourserver/api
. Это делается с помощью переменной среды API_URL_BROWSER .
Все вместе
nuxt.config.js
axios: {
prefix: '/api',
proxy: true
},
proxy: {
'/api/': {
target: process.env.STRAPI_URL || 'http://localhost:1337',
pathRewrite: {
'^/api/': ''
}
}
},
докер-compose.yml
version: '3'
services:
reverseproxy: # see https://docs.traefik.io/#the-traefik-quickstart-using-docker
image: traefik
command: --docker
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
api:
image: strapi/strapi
environment:
- ...
expose:
- 1337
labels:
traefik.frontend.rule: PathPrefixStrip:/api
traefik.port: 1337
nuxt:
image: ...
expose:
- 3000
command:
"npm run start"
environment:
NUXT_HOST: 0.0.0.0
STRAPI_URL: http://api:1337/
API_URL_BROWSER: /api
labels:
traefik.frontend.rule: PathPrefixStrip:/
traefik.port: 3000