Vue.js Router с Nginx некорректно обрабатывает маршрутизацию

Вопрос или проблема

Я разрабатываю одностраничное приложение на VueJS и для локальной разработки использую Docker с файлом docker-compose.yml для управления контейнером Nginx в качестве веб-сервера и контейнером Node для компиляции ресурсов.

На данный момент есть одна страница по маршруту /configurator, на которую должен перенаправляться корневой маршрут /, и с роутером Vue это работает отлично: обращение к / корректно перенаправляется на /configurator.

Проблема возникает при обновлении страницы, поскольку Nginx не может обработать запрос, так как нет подходящего файла по указанному URI для обслуживания.

Документация VueJS указывает, что для перенаправления каждого запроса на индекс проекта и соответственно для того, чтобы роутер Vue мог обрабатывать навигацию, необходимо настроить секцию location в конфигурации Nginx следующим образом:

location / {
  try_files $uri $uri/ /index.html;
}

Поэтому я создал пользовательский файл nginx.conf и добавил/переименовал его в контейнере Nginx через мой файл docker-compose.yml, как указано ниже, но я все равно получаю 404 от Nginx.

Проверяя изнутри контейнера Nginx с помощью nginx -T, я правильно вижу свой пользовательский файл, но заметил, что файл default.conf находится последним в списке, поэтому я подумал, что Nginx добавляет дополнительные файлы в алфавитном порядке, и так как мой не последний, моя пользовательская конфигурация была перезаписана конфигурацией из default.conf. Я отредактировал свой docker-compose.yml, чтобы добавить его под именем z_custom.conf, просто чтобы быть уверенным, что он будет последним, но ничего не изменилось.

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

Правильно ли это или есть способ фактически объединить только мою пользовательскую секцию с всей конфигурацией по умолчанию?

custom.conf

server {
    # Конфигурация роутера Vue
    location / {
        try_files $uri $uri/ /index.html;
    }
}

docker-compose.yml

webserver:
    image: nginx:latest
    container_name: webserver
    restart: unless-stopped
    ports:
      - 80:80
    volumes:
      - ./application/public:/usr/share/nginx/html:ro
      - ./nginx.conf:/etc/nginx/conf.d/custom.conf:ro

Обновление #1: добавление server_name в файл пользовательской конфигурации

Следуя ответу @tero-kilkanen, я просто попробовал добавить server_name localhost внутрь корневой секции server моего конфигурационного файла и обновил docker-compose.yml, чтобы скопировать его внутрь образа Nginx как localhost.conf, но ничего не изменилось, по прежнему получаю 404 на неиндексируемых маршрутах.

Обновление #2

Не заметил раньше, что предыдущее обновление создает конфликт между конфигурацией по умолчанию и пользовательской конфигурацией, так как оба файла объявляют одно и то же имя сервера, поэтому теперь я просто заменяю default.conf своим пользовательским файлом и обновил секцию location следующим образом, но по-прежнему получаю 404 на некорневых маршрутах.

location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
}

Запуск nginx -T и nginx -t подтверждает, что мой пользовательский конфигурационный файл читается и используется правильно:

root@be898ad4ca17:/# nginx -T
nginx: файл конфигурации /etc/nginx/nginx.conf имеет правильный синтаксис
nginx: тест конфигурационного файла /etc/nginx/nginx.conf прошел успешно
# конфигурационный файл /etc/nginx/nginx.conf:

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
}

# конфигурационный файл /etc/nginx/mime.types:

types {
    text/html                                        html htm shtml;
    text/css                                         css;
    text/xml                                         xml;
    image/gif                                        gif;
    image/jpeg                                       jpeg jpg;
    application/javascript                           js;
    application/atom+xml                             atom;
    application/rss+xml                              rss;

    text/mathml                                      mml;
    text/plain                                       txt;
    text/vnd.sun.j2me.app-descriptor                 jad;
    text/vnd.wap.wml                                 wml;
    text/x-component                                 htc;

    image/avif                                       avif;
    image/png                                        png;
    image/svg+xml                                    svg svgz;
    image/tiff                                       tif tiff;
    image/vnd.wap.wbmp                               wbmp;
    image/webp                                       webp;
    image/x-icon                                     ico;
    image/x-jng                                      jng;
    image/x-ms-bmp                                   bmp;

    font/woff                                        woff;
    font/woff2                                       woff2;

    application/java-archive                         jar war ear;
    application/json                                 json;
    application/mac-binhex40                         hqx;
    application/msword                               doc;
    application/pdf                                  pdf;
    application/postscript                           ps eps ai;
    application/rtf                                  rtf;
    application/vnd.apple.mpegurl                    m3u8;
    application/vnd.google-earth.kml+xml             kml;
    application/vnd.google-earth.kmz                 kmz;
    application/vnd.ms-excel                         xls;
    application/vnd.ms-fontobject                    eot;
    application/vnd.ms-powerpoint                    ppt;
    application/vnd.oasis.opendocument.graphics      odg;
    application/vnd.oasis.opendocument.presentation  odp;
    application/vnd.oasis.opendocument.spreadsheet   ods;
    application/vnd.oasis.opendocument.text          odt;
    application/vnd.openxmlformats-officedocument.presentationml.presentation
                                                     pptx;
    application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
                                                     xlsx;
    application/vnd.openxmlformats-officedocument.wordprocessingml.document
                                                     docx;
    application/vnd.wap.wmlc                         wmlc;
    application/wasm                                 wasm;
    application/x-7z-compressed                      7z;
    application/x-cocoa                              cco;
    application/x-java-archive-diff                  jardiff;
    application/x-java-jnlp-file                     jnlp;
    application/x-makeself                           run;
    application/x-perl                               pl pm;
    application/x-pilot                              prc pdb;
    application/x-rar-compressed                     rar;
    application/x-redhat-package-manager             rpm;
    application/x-sea                                sea;
    application/x-shockwave-flash                    swf;
    application/x-stuffit                            sit;
    application/x-tcl                                tcl tk;
    application/x-x509-ca-cert                       der pem crt;
    application/x-xpinstall                          xpi;
    application/xhtml+xml                            xhtml;
    application/xspf+xml                             xspf;
    application/zip                                  zip;

    application/octet-stream                         bin exe dll;
    application/octet-stream                         deb;
    application/octet-stream                         dmg;
    application/octet-stream                         iso img;
    application/octet-stream                         msi msp msm;

    audio/midi                                       mid midi kar;
    audio/mpeg                                       mp3;
    audio/ogg                                        ogg;
    audio/x-m4a                                      m4a;
    audio/x-realaudio                                ra;

    video/3gpp                                       3gpp 3gp;
    video/mp2t                                       ts;
    video/mp4                                        mp4;
    video/mpeg                                       mpeg mpg;
    video/quicktime                                  mov;
    video/webm                                       webm;
    video/x-flv                                      flv;
    video/x-m4v                                      m4v;
    video/x-mng                                      mng;
    video/x-ms-asf                                   asx asf;
    video/x-ms-wmv                                   wmv;
    video/x-msvideo                                  avi;
}

# конфигурационный файл /etc/nginx/conf.d/default.conf:
server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    #error_page  404              /404.html;

    # перенаправить страницы ошибок сервера на статическую страницу /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # проксировать PHP-скрипты к Apache, слушающему на 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # передать PHP-скрипты серверу FastCGI, слушающему на 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # запретить доступ к файлам .htaccess, если корневая папка Apache совпадает с корневой папкой nginx
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

Лучшей практикой является указание server_name в вашем блоке server. Тогда nginx будет использовать этот server блок для вашего приложения, когда вы запрашиваете страницу, используя имя в URL.

Ответ или решение

Проблема, с которой вы столкнулись, связана с маршрутизацией в одностраничном приложении (SPA) на VueJS с использованием Nginx. Ваша конфигурация Nginx должна обеспечивать правильное перенаправление запросов на index.html, чтобы Vue Router мог обрабатывать маршруты во время обновления страницы.

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

1. Корректная конфигурация Nginx

Вам нужно убедиться, что конфигурация сервера Nginx правильно настроена для обработки маршрутов Vue Router. Вот пример полной конфигурации на основе вашего кода:

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;  # Убедитесь, что это название сервера совпадает с тем, что вы используете в URL

    root   /usr/share/nginx/html;  # Укажите директорию, где хранится ваш index.html

    # Основная конфигурация обработки маршрутов
    location / {
        try_files $uri $uri/ /index.html;
    }

    # Обработка ошибок
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

2. Обновление docker-compose.yml

В вашем docker-compose.yml убедитесь, что ваш файл конфигурации Nginx корректно подключен. Вот пример того, как это должно выглядеть:

version: '3'
services:
  webserver:
    image: nginx:latest
    container_name: webserver
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - ./application/public:/usr/share/nginx/html:ro
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro  # Переименуйте свой файл конфигурации

Обратите внимание, что в этом примере nginx.conf переименован в default.conf. Это важно, так как Nginx загружает конфигурацию, находящуюся в файле default.conf. Если вы хотите использовать другой файл, убедитесь, что другие конфигурации так же не конфликтуют.

3. Проверка конфигурации

После того, как вы внесли изменения в конфигурацию, убедитесь, что Nginx читает вашу конфигурацию правильно. Вы можете выполнить команду внутри контейнера:

nginx -T

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

4. Тестирование

После внесения всех изменений и перезапуска контейнера Nginx выполните тест, обновив страницу на маршруте /configurator. Если всё работает корректно, вы должны увидеть результат без ошибок 404.

Заключение

Если у вас по-прежнему возникают проблемы, проверьте также, что у вас нет других конфигурационных файлов, которые могут переопределять ваше поведение (например, другие файлы в /etc/nginx/conf.d/). Если проблема окажется сложнее, рассмотрите возможность добавления логирования в вашем Nginx, чтобы лучше понимать, что происходит при запросах.

Надеюсь, это поможет вам решить проблему с маршрутизацией в VueJS с использованием Nginx! Если у вас есть дополнительные вопросы, не стесняйтесь их задавать.

Оцените материал
Добавить комментарий

Капча загружается...