在 Heroku 上使用 Rails API 部署 Create-React-App

Deploying Create-React-App with Rails API on Heroku

我在让我的 React /rails 应用程序在 heroku 上运行时遇到问题。我已经设法部署它并且 rails 服务器启动,但我没有看到我的 React 应用程序。我觉得我很接近,但无法弄清楚缺少什么。

所以我的进程目前是从客户端目录到 运行 npm run build 本地,这在客户端中构建了一个 'build' 目录。然后我提交构建的结果并使用 git push heroku master.

推送到 Heroku

然后我在浏览器中导航到 heroku 应用程序,在那里我只得到一个空白的白页,这是一个索引文件,我手动从构建目录复制到 public。我不确定索引文件是否正确,但我只是想确保我能命中某些东西。

最终,我只想推送 repo,它会自动 运行 构建。我在不同的地方看到过这个,但是当我在服务器上 运行 npm run build 时,我总是得到一个 react-script does not exist 错误。

我的配置如下:

应用的基本结构

/app - root of Rails app
/client - root of React app
/public - does display index page

root/client/package.json

{
    "name": "qc_react",
    "version": "0.1.0",
    "private": true,
    "devDependencies": {
        "react-scripts": "^0.8.4"
    },
    "dependencies": {
        "react": "^15.4.1",
        "react-dom": "^15.4.1",
        "react-router": "^3.0.0"
    },
    "scripts": {
        "start": "react-scripts start",
        "build": "react-scripts build",
        "test": "react-scripts test --env=jsdom",
        "eject": "react-scripts eject"
    },
    "cacheDirectories": [
        "node_modules",
        "client/node_modules"
    ],
    "proxy": "${API_URL}:${PORT}/v1/"
}

root/package.json

{
  "name": "web",
  "version": "1.0.0",
  "description": "This repo contains a web application codebase. Read instructions on how to install.",
  "main": "index.js",
  "scripts": {
    "build": "cd client" # not sure what to put here but this gets me past build failure
  },
  "repository": {
    "type": "git",
    "url": "git+ssh://myrepo.git"
  },
  "author": "",
  "license": "ISC",
  "homepage": "https://myhomepage#readme"
}

过程文件

api: bundle exec puma -C config/puma.rb

构建包

1. https://github.com/mars/create-react-app-buildpack.git
2. heroku/ruby

config/puma.rb

workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 5)
threads threads_count, threads_count

preload_app!

rackup      DefaultRackup
port        ENV['PORT']     || 3001
environment ENV['RACK_ENV'] || 'development'

on_worker_boot do
  # Worker specific setup for Rails 4.1+
  # See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
  ActiveRecord::Base.establish_connection
end

我看到您正在使用 create-react-app-buildpack,但我认为您的问题是您的 React 应用程序位于子目录中。只有当 heroku 可以在目录中检测到匹配的应用程序时,Buildpacks 才会被执行,因为你的根目录中的 package.json 与 create-react-app-buildpack 不匹配,我认为它没有被使用。

您可以尝试删除根 package.json 并使用此 sub directory buildpack 以便您可以指定每个 buildpack 目录的位置

那是因为 Rails 正在提供来自 /public 的静态文件(包括 index.html)。但是您的 React 应用程序包位于 /client/build 内。构建后,您需要将这些文件复制回 Rails 文件夹。最简单的方法是将一些脚本添加到 package.json:

"scripts": {
  ...
  "deploy": "cp -a build/. public",
  "heroku-postbuild": "npm run build && npm run deploy"
},

heroku-postbuild 在安装所有依赖项后由 Heroku 自动执行,就像普通的 postinstall hook.

注意 cp 命令的路径。您使用 2 个不同的 package.json 文件进行的设置太复杂了。我建议在 root 中使用单个 package.json 并相应地设置所有路径。

所以我终于找到了我正在寻找的解决方案。我的代码库具有以下结构。

app/
client/
public/
...

我目前正在按照@yeasayer 上面的建议构建我的客户端解决方案。在构建并将我的 React 项目部署到 rails api 中的 public 文件夹后,我将以下内容添加到我的路由中:

... # api routes ...

get '/*path', to: 'react#index'

然后我创建了一个react_controller并添加了以下内容:

class ReactController < ActionController::Base
  def index
      render :file => 'public/index.html', :layout => false
  end
end

现在,任何未被 api 路由捕获的路由都将呈现 React 应用程序。我不确定为什么其他人不使用此结构而不是使用 react_on_rails 或其他一些插件来获得相同的结果。此设置比处理这些其他解决方案要简单得多,但我想听听有关为什么此解决方案不是一个好主意的任何想法。