erikras / react-redux-universal-hot-example

A starter boilerplate for a universal webapp using express, react, redux, webpack, and react-transform
MIT License
12.01k stars 2.5k forks source link

slow deployment on heroku #1161

Open jtmarmon opened 8 years ago

jtmarmon commented 8 years ago

Our deploys on heroku are taking quite a long time (30+ seconds) which incurs quite a bit of downtime during deployment. A second or two is acceptable, but 30 seconds is not. Any idea on how I can improve the speed of npm start? Locally it runs significantly faster...

From logs:

2016-05-18T17:39:01.756601+00:00 heroku[web.1]: Starting process with command `npm start`
2016-05-18T17:39:05.413614+00:00 app[web.1]:
2016-05-18T17:39:05.413630+00:00 app[web.1]: > react-redux-universal-hot-example@0.9.0 start /app
2016-05-18T17:39:05.413631+00:00 app[web.1]: > concurrent --kill-others "npm run start-prod"
2016-05-18T17:39:05.413632+00:00 app[web.1]:
2016-05-18T17:39:07.267232+00:00 app[web.1]: [0]
2016-05-18T17:39:07.267242+00:00 app[web.1]: [0] > react-redux-universal-hot-example@0.9.0 start-prod /app
2016-05-18T17:39:07.267243+00:00 app[web.1]: [0] > better-npm-run start-prod
2016-05-18T17:39:07.267243+00:00 app[web.1]: [0]
2016-05-18T17:39:07.465188+00:00 app[web.1]: [0] Executing script: start-prod
2016-05-18T17:39:07.431925+00:00 app[web.1]: [0] running better-npm-run in /app
2016-05-18T17:39:07.465198+00:00 app[web.1]: [0]
2016-05-18T17:39:07.465198+00:00 app[web.1]: [0] to be executed: node ./bin/server.js
2016-05-18T17:39:38.524212+00:00 app[web.1]: [0] ----
2016-05-18T17:39:38.524224+00:00 app[web.1]: [0] ==> ✅  React Redux Example is running, talking to API server on 3000.
2016-05-18T17:39:38.524843+00:00 app[web.1]: [0] ==> 💻  Open http://localhost:20037 in a browser to view the app.1
jaraquistain commented 8 years ago

I know that this isn't a helpful answer to this question but realistically speaking any app that grows in size is going to get to a point where deployments take a non trivial amount of time and so my advice in this case would be to investigate engineering a rolling deployment solution such that no downtime at all is experienced to an end-user regardless of how long an individual deployment takes.

I'm not terribly familiar with the workings of heroku so I can't advise on a solution specific to that platform, but 2 general methods are to have multiple workers running on a single instance of your app that can shut down and restart with new code in a staggered way and another is to have multiple instances of your app with a load balancer in front of it and deploy to your instances in serial, moving on to the next only when the last has started

jtmarmon commented 8 years ago

yeah i don't expect 0 downtime and I understand rolling deployments would solve this issue, but i'd rather stay on the hobby tier for now and it just seems quite excessive to take 30 seconds to start...keep in mind this is after webpack is built, so literally just running the server takes 30 seconds

Dattaya commented 8 years ago

@jtmarmon, maybe pre-building an app with babel would help, something like this "build:server": "rimraf ./build && babel src -d build --copy-files", and then you can require babel-register conditionally, only for development:

if (__DEVELOPMENT__) {
  require('babel-register')({});
}
kengoldfarb commented 8 years ago

@jtmarmon - Here's an example you can check out that solves the heroku boot time issue: https://github.com/kengoldfarb/react-redux-universal-hot-example/pull/1/files

I've got a project based on this framework with a large codebase and have also seen the heroku build times become increasingly problematic...to the point that my app is failing to boot and I get the R10 Boot Timeout error.

@Dattaya is spot-on that pre-building w/ babel-cli will fix this issue.

You'll still have a few seconds of downtime on deploy (using free/hobby tier), but it's nowhere near what it is with runtime transpilation.

@erikras - Is this something you'd want to incorporate back into the heroku branch?

Hope this helps!

Changes of note:

const styles = require('./App.scss') || {};
Dattaya commented 8 years ago

I also had to change the entry point in webpack.prod.config.js to point to './build/client.js' instead of './src/client.js'(ofc babel loader is no longer necessary in prod.config), otherwise there was some mistake with styles. I guess alternatively it could be solved with require('./App.scss') || {};? Tangentially related to #889