Reputation: 707
I'm having an issue getting my react /rails app to work on heroku. I've managed to get it deployed and the rails server starts but I'm not seeing my react app. I feel like I'm close but can't figure out what's missing.
So my process is currently to run npm run build
locally from the client directory which builds a 'build' directory in client. I then commit the results of the build and push to Heroku with git push heroku master
.
I then navigate to the heroku app in a browser where I'm only getting a blank white page which is an index file the I manually copied from the build dir to public. I'm not sure if the index file is correct but I just wanted to make sure i could hit something.
Ultimately, I would like to just push the repo and it automatically run the build. I've seen this mentioned various places but I always get a react-script does not exist error when I run npm run build
on the server.
My configuration is as follows:
basic structure of app
/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"
}
Procfile
api: bundle exec puma -C config/puma.rb
Buildpacks
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
Upvotes: 3
Views: 1423
Reputation: 707
So I finally found the solution I was looking for. My code base has the following structure.
app/
client/
public/
...
I'm currently building my client solution as @yeasayer suggested above. After building and deploying my react project to the public folder in my rails api, I added the following to my routes:
... # api routes ...
get '/*path', to: 'react#index'
Then I created a react_controller and added the following contents:
class ReactController < ActionController::Base
def index
render :file => 'public/index.html', :layout => false
end
end
Now any routes not caught by the api routes, will render the react app. I'm not sure why others don't use this structure instead of using react_on_rails or some other plugin to achieve the same result. This setup is a lot simpler than dealing with these other solutions but I'd like to hear any thoughts on why this solution is not a good idea.
Upvotes: 2
Reputation: 868
That's because Rails is serving static files (including index.html
) from /public
. But your React app bundle is located inside /client/build
. After build you need to copy these files back to Rails folder. The easiest way to do this is to add some scripts to your package.json
:
"scripts": {
...
"deploy": "cp -a build/. public",
"heroku-postbuild": "npm run build && npm run deploy"
},
heroku-postbuild
is executed automatically by Heroku after all dependencies are installed, just like normal postinstall
hook.
Be careful with the paths for cp
command. Your setup with 2 different package.json
files is too complex. I recommend to use a single package.json
inside root and set all paths accordingly.
Upvotes: 3
Reputation: 1
I see you are using the create-react-app-buildpack, but I think your issue is that your react app is in a subdirectory. Buildpacks only get executed if heroku can detect a matching application in the directory and since your package.json in your root does not match create-react-app-buildpack I don't think it is being used.
What you might try is removing the root package.json and using this sub directory buildpack so you can specify the locations of each buildpack directory
Upvotes: 0