Развертывание API Rails 7 с фронтендом на React с использованием Vite на Heroku

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

Я создал базовый API на Rails 7 с фронтендом на React, используя Vite. Проект также был создан с помощью:

npm create vite@latest

команды, если это полезно для понимания контекста. Проблема, с которой я сталкиваюсь, заключается в том, что приложение работает нормально локально, но компоненты/маршруты не отображаются на Heroku.

Приложение использует React Router для обработки маршрутизации, поэтому я понимаю, что это вызовет проблему с тем, что маршруты не отображаются так, как ожидалось через Heroku, из-за того, что контент рендерится на стороне клиента. Я пытался решить это с помощью Nginx buildpack для Heroku.

Тем не менее, мне не удается успешно отобразить мои компоненты после развертывания, несмотря на то, что я настроил NodeJS, Ruby и Nginx buildpack (в этом порядке) и следовал множеству похожих постов здесь:

Вот некоторые скриншоты и файлы для справки:

Структура файлов

Снова, это приложение было настроено с помощью команды Vite выше, так что эта структура предоставлена из коробки.

введите описание изображения здесь

Похоже, что Heroku может искать мой файл vite.config.js в каталоге /app/frontend/ вместо каталога /frontend/ на основе логов Heroku:

введите описание изображения здесь

Package.json

{
  "name": "frontend",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  },
  "dependencies": {
    "@emotion/react": "^11.13.3",
    "@emotion/styled": "^11.13.0",
    "@fontsource/roboto": "^5.1.0",
    "@mui/icons-material": "^6.1.1",
    "@mui/material": "^6.1.1",
    "@mui/styles": "^6.1.1",
    "@mui/x-data-grid": "^7.18.0",
    "@mui/x-date-pickers": "^7.18.0",
    "axios": "^1.7.7",
    "dayjs": "^1.11.13",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router-dom": "^6.26.2"
  },
  "devDependencies": {
    "@eslint/js": "^9.9.0",
    "@types/react": "^18.3.3",
    "@types/react-dom": "^18.3.0",
    "@vitejs/plugin-react": "^4.3.1",
    "eslint": "^9.9.0",
    "eslint-plugin-react": "^7.35.0",
    "eslint-plugin-react-hooks": "^5.1.0-rc.0",
    "eslint-plugin-react-refresh": "^0.4.9",
    "globals": "^15.9.0",
    "vite": "^5.4.1"
  }
}

nginx.conf.erb

daemon off;
# У Heroku dynos минимум 4 ядра.
worker_processes <%= ENV['NGINX_WORKERS'] || 4 %>;

events {
    use epoll;
    accept_mutex on;
    worker_connections <%= ENV['NGINX_WORKER_CONNECTIONS'] || 1024 %>;
}

http {
    gzip on;
    gzip_comp_level 2;
    gzip_min_length 512;
    gzip_proxied any; # маршрутизатор Heroku отправляет заголовок Via

    server_tokens off;

    log_format l2met 'measure#nginx.service=$request_time request_id=$http_x_request_id';
    access_log <%= ENV['NGINX_ACCESS_LOG_PATH'] || 'logs/nginx/access.log' %> l2met;
    error_log <%= ENV['NGINX_ERROR_LOG_PATH'] || 'logs/nginx/error.log' %>;

    include mime.types;
    default_type application/octet-stream;
    sendfile on;

    # Необходимо прочитать тело за 5 секунд.
    client_body_timeout 5;

    upstream app_server {
        server unix:/tmp/nginx.socket fail_timeout=0;
    }

    server {
        listen <%= ENV["PORT"] %>;
        server_name _;
        keepalive_timeout 5;

        location / {
            # Раскомментируйте это условие, чтобы принудительно использовать SSL/перенаправить http -> https
            # if ($http_x_forwarded_proto != "https") {
            #   return 301 https://$host$request_uri;
            # }

            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect off;
            proxy_pass http://app_server;
        }
    }
}

vite.json

{
  "all": {
    "sourceCodeDir": "frontend",
    "watchAdditionalPaths": []
  },
  "development": {
    "autoBuild": true,
    "publicOutputDir": "vite-dev",
    "port": 3036
  },
  "test": {
    "autoBuild": true,
    "publicOutputDir": "vite-test",
    "port": 3037
  }
}

vite.config.js

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      '/api': {
        target: 'https://fake.herokuapp.com/', // Раскомментируйте эту строку при развертывании на Heroku
        // target: 'http://localhost:3000', // Раскомментируйте эту строку при разработке локально - Замените на ваш URL API Rails
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, ''),
      },
    },
  },
})

Буду признателен за любые советы!

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

Для развертывания вашего приложения на Heroku с использованием Rails 7 API и React-фронтенда, созданного с помощью Vite, выполните следующие шаги. Я постараюсь подробно объяснить, как правильно настроить среду, чтобы всё работало корректно.

Шаг 1: Настройка папки проекта

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

/app
/frontend
  /src
  vite.config.js
  package.json
/RailsBackend
  ...

Где /frontend – это ваша папка с Vite-приложением. Важно, чтобы все настройки ссылались на правильные директории.

Шаг 2: Конфигурация Nginx

Вы правильно настраиваете Nginx для проксирования запросов. В вашем nginx.conf.erb добавьте следующие строки, чтобы обеспечить поддержку маршрутизации для вашего React-приложения. Это позволит выполнять корректную маршрутизацию на стороне клиента.

location / {
    try_files $uri $uri/ /index.html;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
}

Шаг 3: Настройка npm и Vite

Убедитесь, что у вас установлен правильный скрипт сборки для деплоя. В вашем package.json нужно убедиться, что вы выполняете команду сборки:

"scripts": {
  "dev": "vite",
  "build": "vite build",
  "start": "vite preview" // Добавьте эту строку
}

Шаг 4: Конфигурация Heroku

  1. Добавление buildpack-ов: Убедитесь, что вы добавили Node.js, Ruby и Nginx buildpacks в правильном порядке.

    heroku buildpacks:add --index 1 heroku/nodejs
    heroku buildpacks:add --index 2 heroku/ruby
    heroku buildpacks:add --index 3 https://github.com/heroku/heroku-buildpack-nginx
  2. Настройка переменных среды: Убедитесь, что у вас правильно настроены переменные окружения. Обычно вам нужно добавить переменные, такие как RAILS_ENV и NODE_ENV, чтобы убедиться, что во время сборки используется правильная конфигурация.

    heroku config:set RAILS_ENV=production NODE_ENV=production

Шаг 5: Сборка приложения

После внесения всех изменений выполните сборку вашего Vite приложения и деплой на Heroku:

git add .
git commit -m "Configure deployment for Heroku"
git push heroku main

Шаг 6: Логи и отладка

Если после развертывания возникли проблемы с отображением компонентов или маршрутизации, вам следует проверить логи Heroku:

heroku logs --tail

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

Шаг 7: Проверка выполнения

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

Заключение

Если после выполнения всех шагов у вас все еще возникают проблемы, возможно, стоит проверить конфигурацию вашего маршрутизатора в React, особенно в случае, если вы используете динамические пути. Убедитесь, что ваше приложение правильно обрабатывает 404 ошибки и маршрутизацию на стороне клиента. В случае дополнительных вопросов не стесняйтесь обращаться к сообществу или документации Heroku.

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

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