在 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 或其他一些插件来获得相同的结果。此设置比处理这些其他解决方案要简单得多,但我想听听有关为什么此解决方案不是一个好主意的任何想法。
我在让我的 React /rails 应用程序在 heroku 上运行时遇到问题。我已经设法部署它并且 rails 服务器启动,但我没有看到我的 React 应用程序。我觉得我很接近,但无法弄清楚缺少什么。
所以我的进程目前是从客户端目录到 运行 npm run build
本地,这在客户端中构建了一个 'build' 目录。然后我提交构建的结果并使用 git push heroku master
.
然后我在浏览器中导航到 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 或其他一些插件来获得相同的结果。此设置比处理这些其他解决方案要简单得多,但我想听听有关为什么此解决方案不是一个好主意的任何想法。