Stack Overflow Question
Host Provider Heroku doesn't seem to pick up concurrently command in "npm run start". I can get this start command to work with "heroku local web" but get the below log errors when running the same thing on heroku host. I noticed that for some other node full stack projects, the backend is setup to run on startup. In these cases there is routing setup in express so that the request either routes to a backend route or is passed off to a static front endpape. My issues is that I don't have express to support this. I'm just running json-server on the backend (or trying) and my vue.js content on the front.
Is there a work around to get Heroku configured to start both the a front and backend server?
I can run the "npm run start" locally but not on Heroku: It seems like Heroku (at least by default) is configured to start a node app by running "npm run start". As a result, I have the following entry in my package.json:
package.json
"start": "concurrently \"export NODE_ENV=production\" \"json-server --watch db.json\" \"vue-cli-service serve --mode production\""
Heroku Logs:
2021-10-17T18:30:52.000000 00:00 app[api]: Build succeeded
2021-10-17T18:30:54.001782 00:00 heroku[web.1]: Starting process with command `npm start`
2021-10-17T18:30:55.002829 00:00 app[web.1]:
2021-10-17T18:30:55.002845 00:00 app[web.1]: > my-vue-app@0.1.0 start /app
2021-10-17T18:30:55.002845 00:00 app[web.1]: > concurrently "export NODE_ENV=production" "json-server --watch db.json" "vue-cli-service serve --mode production"
2021-10-17T18:30:55.002846 00:00 app[web.1]:
2021-10-17T18:30:55.226381 00:00 app[web.1]: [1] /bin/sh: 1: json-server: not found
2021-10-17T18:30:55.227075 00:00 app[web.1]: [2] /bin/sh: 1: vue-cli-service: not found
2021-10-17T18:30:55.228104 00:00 app[web.1]: [2] vue-cli-service serve --mode production exited with code 1272021-10-17T18:30:55.228540 00:00 app[web.1]: [1] json-server --watch db.json exited with code 127
2021-10-17T18:30:55.228781 00:00 app[web.1]: [0] export NODE_ENV=production exited with code 0
2021-10-17T18:30:55.238234 00:00 app[web.1]: npm ERR! code ELIFECYCLE
2021-10-17T18:30:55.238413 00:00 app[web.1]: npm ERR! errno 1
2021-10-17T18:30:55.242355 00:00 app[web.1]: npm ERR! my-vue-app@0.1.0 start: `concurrently "export NODE_ENV=production" "json-server --watch db.json" "vue-cli-service serve --mode production"`
2021-10-17T18:30:55.242419 00:00 app[web.1]: npm ERR! Exit status 1
2021-10-17T18:30:55.242477 00:00 app[web.1]: npm ERR!
2021-10-17T18:30:55.242529 00:00 app[web.1]: npm ERR! Failed at the my-vue-app@0.1.0 start script.
2021-10-17T18:30:55.242567 00:00 app[web.1]: npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
2021-10-17T18:30:55.248113 00:00 app[web.1]:
2021-10-17T18:30:55.248206 00:00 app[web.1]: npm ERR! A complete log of this run can be found in:
2021-10-17T18:30:55.248255 00:00 app[web.1]: npm ERR! /app/.npm/_logs/2021-10-17T18_30_55_242Z-debug.log
2021-10-17T18:30:55.386385 00:00 heroku[web.1]: Process exited with status 1
2021-10-17T18:30:55.642820 00:00 heroku[web.1]: State changed from starting to crashed
2021-10-17T18:30:59.838564 00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=myvueapp1.herokuapp.com request_id=eaa81f4f-8d66-4dcc-92e6-5ac730cf9c9c fwd="73.181.221.158" dyno= connect= service= status=503 bytes= protocol=https
2021-10-17T18:31:00.272840 00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" host=myvueapp1.herokuapp.com request_id=a3108da6-5ba3-48cf-8bc4-4b5784a6d171 fwd="73.181.221.158" dyno= connect= service= status=503 bytes= protocol=https
2021-10-17T18:32:51.000000 00:00 app[api]: Build started by user mark.johnson.
2021-10-17T18:33:54.181436 00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=myvueapp1.herokuapp.com request_id=91cd8f28-f155-4b58-b4ac-bb1539e06413 fwd="73.181.221.158" dyno= connect= service= status=503 bytes= protocol=https
2021-10-17T18:33:54.362762 00:00 heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/favicon.ico" host=myvueapp1.herokuapp.com request_id=8103d63b-9a7d-46f9-b2c1-5d662e77b539 fwd="73.181.221.158" dyno= connect= service= status=503 bytes= protocol=https
2021-10-17T18:34:35.091986 00:00 heroku[web.1]: State changed from crashed to starting
2021-10-17T18:34:34.685663 00:00 app[api]: Deploy 6abb4c8b by user mark.johnson.
2021-10-17T18:34:34.685663 00:00 app[api]: Release v4 created by user mark.johnson.
2021-10-17T18:34:38.788809 00:00 heroku[web.1]: Starting process with command `npm start`
2021-10-17T18:34:41.024848 00:00 app[web.1]:
2021-10-17T18:34:41.024866 00:00 app[web.1]: > my-vue-app@0.1.0 start /app
2021-10-17T18:34:41.024866 00:00 app[web.1]: > concurrently "export NODE_ENV=production" "json-server --watch db.json" "vue-cli-service serve --mode production"
2021-10-17T18:34:41.024867 00:00 app[web.1]:
2021-10-17T18:34:41.548998 00:00 app[web.1]: [1] Done
2021-10-17T18:34:41.555274 00:00 app[web.1]: [1]
2021-10-17T18:34:41.555534 00:00 app[web.1]: [1] Resources
2021-10-17T18:34:41.555535 00:00 app[web.1]: [1] http://localhost:3000/table1
2021-10-17T18:34:41.555535 00:00 app[web.1]: [1] http://localhost:3000/table2
2021-10-17T18:34:41.555535 00:00 app[web.1]: [1]
2021-10-17T18:34:41.555536 00:00 app[web.1]: [1] Home
2021-10-17T18:34:41.555536 00:00 app[web.1]: [1] http://localhost:3000
2021-10-17T18:34:41.555536 00:00 app[web.1]: [1]
2021-10-17T18:34:41.555781 00:00 app[web.1]: [1] Type s enter at any time to create a snapshot of the database
CodePudding user response:
As I said here and here, the common approach in an enterprise architecture is to have one app by repository and server.
Imagine that your microservice (json) process needs to have more ram because handle heavy operations and since your web is an spa, does not need anything because it is just static files after npm run build
. In this case, depending of the infrastructure, you could scale vertically/horizontally every artifact (api and web) easily. If you have several process in the same server, you would be backing up a little to the monolithic architecture. This is just one of the several advantages like:
- https://michaelwashburnjr.com/blog/4-reasons-web-app-separated-frontend-backend
- https://softwareengineering.stackexchange.com/a/299550/204271
Api and Web
In heroku and any platform, applications has its own port. Also you will have noticed that in your developer laptop:
- vue app runs at : http://localhost:8080
- api mock at http://localhost:3000/posts/1
As you can see , you have two apps here, each one with its own port. In the future, each one will have its own domain : acme.com and acme-api.com
Just for test
The usage of json-server to publish a single file (db.json) as a microservice or rest api is just for testing or poc purposes. It would be crazy to use concurrently in a real application for real users.
I used this on early development stage, when the api/microservice does not exist yet.
When api is ready to use and has its own http domain (http://acme-api.com) served on its own server, I set this new url on my web.
Two apps (api web)
If you don't want to complicate and be prepared for a real enterprise deployment, you should create two different app on your heroku account
- acme-web with your vue code. This usually needs to have the
npm run dev
,npm run build
andnpm run start
. Your start script should be something like this:"start": "vue-cli-service serve --mode production"
- acme-api with your real api/microservice source code(database connection and other features). Also in early stage (api does not exist yet) you could put here your db.json and you start script should look like this:
"start": "json-server --watch db.json"
One app
Anyway, if you want or need to have all (web api) in one server or container, you should use another provider like aws, gcp, azure, etc. On that provider your concurrently command will work.
On heroku, you can't run two diferent web process on the same dyno.
Workaround
As some framework does like MEAN, MERN & MEVN and other modern monolithics, you could use an express server to serve your api and your web.
This app should look like this:
var express = require('express');
var jsonServer = require('json-server');
var app = express();
//publish the static result of npm run build (vue)
//https://github.com/jrichardsz/nodejs-express-snippets/tree/master/simple-static-server
app.use('/',
express.static(path.join(__dirname, "site" || proces.env.SITE_FOLDER)),
);
//run json-server programmatically here
//https://github.com/typicode/json-server/issues/253#issuecomment-205509836
app.use('/api', jsonServer.router('db.json'));
app.listen(3000);
Variables by environment
If you opt for and advanced distributed architecturem and yo have at least two environments: testing and production and you don't want to change the variables from time to time when you switch your application from your laptop to next environments dev > testing > production
you will need to properly handle your environment variables using the heroku manager.