Deploying a Gulp app to Heroku in a subdirectory - node.js

I'm trying to deploy a Rails/Angular app to Heroku.
Part of my directory structure looks like this:
client/package.json
client/gulpfile.js
My package.json and gulpfile.js aren't at the root; they're in a subdirectory.
The Heroku Node buildpack of course expects package.json to be at the root. How can I get Heroku to recognize my Gulp/Angular app?

Here's how you can do it without a custom buildpack:
Add the node heroku buildpack
heroku buildpacks:add --index 1 https://github.com/heroku/heroku-buildpack-nodejs
Add a package.json to the root of your rails project.
Add a postinstall or a heroku-postbuild script to the top-level package.json like this:
//top-level package.json
"scripts": {
"postinstall": "cd client && npm install && gulp build"
}
Add client/node_modules to the Heroku cache by adding this to the top-level package.json:
//top-level package.json
"cacheDirectories": ["client/node_modules"]
Enjoy
Source:
https://devcenter.heroku.com/articles/nodejs-support#customizing-the-build-process

You'd need to use a custom buildpack to build your front end: https://devcenter.heroku.com/articles/buildpack-api#composing-multiple-buildpacks. You'd compose this custom buildpack with the Rails buildpack to get a complete build working.
The nodejs buildpack has examples on how to run npm install and load package.json which may be helpful.

Related

How to run Procfile with multiple commands on Heroku?

I'm trying to deploy the static website to Heroku and I struggle how to correctly setup the Procfile.
I have next command to run on the server:
npm install
gulp build (will make a build with /public folder)
http-server (will serve /public by default)
What I've tried:
web: npm install; gulp build; http-server
web: npm install & gulp build & http-server
Okay, so I've spent a bit of time on that and came up with the answer. By default, heroku is installing all packages from the package.json file, so npm install is no longer required. Then what was left - gulp build and http-server.
For that case, I've added "postinstall" : "gulp build" to my package.json and it left me with web: http-server.
Simplifying things have actually solved the problem. Not sure how useful that information might be to you, but it's worth to share.
You may also have been looking for && or a library like concurrently.
Regardless, and per the docs, use Procfile as nothing more than an entry point to your npm start script.
Use the npm scripts lifecycle as stated (npm-scripts).
Directly From The Documentation (heroku-build-process).
"scripts": {
"start": "node index.js",
"test": "mocha",
"postinstall": "bower install && grunt build"
}
Heroku has adopted the 'there's an app for everything' mantra, but for buildpacks. Whatever you're building, there's a buildpack for it.
You can run multiple command inside Procfile using sh -c command :
worker: sh -c 'firstCommand && secondCommand && etc...'
Notes : Procfile should be at the project root level.
For example :
worker: sh -c 'cd backend && yarn install && yarn build && yarn start-worker'
Or in your case (if u have Procfile at the same level as package.json) :
web: sh -c 'npm install && gulp build && npm run http-server'

How do I deploy my Typescript Node.js app to Heroku?

When testing locally I was previously running:
"build-live": "nodemon --exec ./node_modules/.bin/ts-node -r dotenv/config -- ./index.ts"
I then figured my Procfile should be something like:
web: ./node_modules/.bin/ts-node -- ./index.ts
But it says module 'typescript' not found, even when it is in package.json. I read in a few places that ts-node is not the way to go to deploy to Heroku, so I am not sure what to do.
UPDATE: I think I am supposed to compile it, so I tried:
web: ./node_modules/.bin/tsc --module commonjs --allowJs --outDir build/ --sourceMap --target es6 index.ts && node build/index.js
This succeeds, however when actually running it, a bunch of the libs I'm using get "Cannot find module '...'".
Alternatively you can have the TypeScript compile as a postinstall hook and run node build/index.js as the only Procfile command:
Your package.json should contain a postinstall hint that gets executed after npm install and before the node process launches:
"scripts": {
"start": "node build/index.js",
"build": "tsc",
"postinstall": "npm run build"
}
You can then leave your Procfile as is:
web: npm start
This 'build on deploy' approach is documented by Heroku here.
The command you've given Heroku is to launch the web "process" by compiling index.ts and dependencies and starting node at index.js. Depending on how things are timed, index.js might or might not exist at the time node starts.
You need to already have your sources compiled by the time you want to start your app. For example, web should just be web: node index.js or similar.
Each build process is different, so you need to figure that out for your own setup. But, suppose you have a classical setup where you push to git and then Heroku picks up that change and updates the app with the new slug. You could just compile things locally and include index.js and any other build output in the repository, for it to be available in the slug for Heroku to use.
A better approach is to use a build server which has an integration with Heroku. After you do the build there, configure it to send the build results to Heroku. Travis has a straighforward setup like this. This way you don't need to include build outputs in your repository, which is considered an anti-pattern.
On a sidenode, try using a tsconfig.json to keep the tsc configuration. It will save you from having to write such long command lines all over the place.
Fabian said that we could do something like:
"scripts": {
"start": "node build/index.js",
"build": "tsc",
"postinstall": "npm run build"
}
As of me writing this, I tested this and can state: postinstall is not required since build script is ran by Heroku. If you want to do it without build script, then you can use heroku-postbuild which will run after dependencies are installed there you run tsc to compile.
My problem was about missing Typescript npm modules. The Typescript compiler tsc was not found when deployed the app to Heroku.
The Heroku deploy process (rightly) does not install development dependencies, in my case the Typescript module was part of devDependencies and thus the tsc command was not running on the Heroku platform.
Solution 1
Add typescript to dependencies: npm i typescript -s
Solution 2
Open Heroku console:
Select console type:
Run the command npm i typescript && npm run tsc
Install typescript as a dev dependency (cf. https://www.typescriptlang.org/download). Once built, your app does not need typescript anymore!
npm install -D typescript
Then in your package.json:
{
"main": "index.js", // <- file will be generated at build time with `tsc`
"scripts": {
"build": "tsc",
"start": "node ."
"start:dev": "ts-node index.ts" // idem, install ts-node as a dev dependency
}
}
The key point here is "build": "tsc".
Why?
Heroku does install all dependencies during build and remove the dev dependencies before the app is deployed (source here).
Node.js deployments will automatically execute an app’s build script during build (since March 11. 2019 source here)
In package.json
"scripts": {
"tsc": "./node_modules/typescript/bin/tsc",
"postinstall": "npm run tsc"
},
Works for me for Heroku deployment.
Installing typescript npm install -D typescript and writing tsc in the build script "build": "tsc", does not work for me. Also, try to run npm i typescript && npm run tsc in the Heroku console which also does not work.
In my case, I remove some dependencies from "devDependencies" to "dependencies", so it goes like this:
"dependencies": {
// The other dependencies goes here, I don't touch them.
// But all TS dependencies I remove to here.
"ts-node": "^9.1.1",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.2.3",
"ts-loader": "^8.0.18"
},

Heroku build for node app with unusual folder structure

The project is divided into a backend code and react native client code.
Both are sharing one github project. It looks like this:
backend/
--- src/
--- package.json
client/
--- src/
--- package.json
For my heroku instance, I want to run only the backend code, but at the same time want to use continues integration feature from github.
Is there a way to make heroku run npm install & start only from the backend folder?
Create a package.json in the root of the whole project (the parent dir of backend). You can do this with npm init --yes.
Give that top-level package.json file two scripts:
"scripts": {
"postinstall": "cd backend && npm install",
"start": "cd backend && npm start"
}
Should do the trick.

How to deploy node that uses Webpack to heroku

I'm using webpack.
Also I don't commit npm_modules folder and public folder, where all generated files are. And I can't figure out how to build my app (I have webpack build command) after deploy and setup my server (it's already looking for public folder).
It seems me a bad idea to commit before upload. Maybe there are some gentle decisions... Any thoughts?
Forked from: How to deploy node that uses Gulp to heroku
"heroku-postbuild": "webpack -p --config ./webpack.prod.config.js --progress"
this is better because if you use postinstall, everytime you do npm i the build script get fired
Do it in a postinstall script as suggested by #orlando:
"postinstall": "webpack -p --config ./webpack.prod.config.js --progress"
In this approach make sure to heroku config:set NODE_ENV=production heroku config:set NPM_CONFIG_PRODUCTION=true
OR
You can find this custom buildpack heroku-buildpack-webpack usable.
These links might help you build understanding:
heroku hook-things-up
npm scripts
In 2019, the simplest way to do this is to use the heroku/nodejs buildpack (automatically selected if you have a package.json at the root of the repository) and add a build script to package json:
"build": "webpack --mode production --config ./webpack.prod.config.js"
Heroku will automatically run this script on deploy. Bonus points because this is the intuitive script to run to test the build locally or in CI.
This is described in Heroku's Best Practices for Node.js Development document:
npm’s lifecycle scripts make great hooks for automation. Heroku provides custom hooks that allow you to run custom commands before or after we install your dependencies. If you need to run something before building your app, you can use the heroku-prebuild script. Need to build assets with grunt, gulp, browserify, or webpack? Do it in a build script.

How to run Bower on Heroku

I'm trying to deploy a NodeJs App on Heroku and this app uses bower.
I did what have been suggested here, but I'm having this error on Heroku after a push:
bower error status code of git: 128
Here is what I use in my app:
Adding proper scripts to package.json
"scripts": {
"start": "node web.js",
"postinstall": "bower cache clean && bower install"
},
Add bower to dependency list
"dependencies": {
...
"bower": "~1.3.12",
...
},
Publishing flow for Heroku is following
It pulls recent version
Runs install
Runs postinstall
Runs start
My Sample
https://github.com/gevorg/typeitquick/blob/master/package.json
Well, doing that may not fix this problem, but you can use
git config --global url."https://".insteadOf git://
to tell git to use HTTPS instead of GIT which worked out for me to install npm dependencies.
Apparently people have cleaned their cache?
https://github.com/bower/bower/issues/50
You can run arbitrary commands on your heroku host by using:
heroku run console

Resources