Heroku build for node app with unusual folder structure - node.js

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.

Related

Creating StoryBook build using cross-env

We're using Storybook platform to build UI components and pages in isolation. According to Storybook documentation, an npm package can be published with npm publish command after it's been built. But first they say that it needs to be built with this command:
{
"scripts": {
"build": "cross-env BABEL_ENV=production babel src -d dist"
}
}
This creates dist folder which looks like this:
My issue is that it doesn't include any .css or .json files that are part of the project. So I have to move them there manually.
Any idea how can I configure the project to include them automatically so I don't have to do it each time I run the build command?

Convert ts-node package.json script to nodejs package.json script when building

I have a TypeScript project with this structure:
root
src
index.ts
package.json
dist
index.js
package.json
This will be hosted in Azure Web Apps. Currently I have my start script more or less like this:
"start": "ts-node index.ts"
I would like build to dist/ folder and have the script be:
"start": "node index.js"
As I will only be deploying contents of dist/. Grunt is used to build/copy (I've found this package called grunt-replace but I don't know if that's a good approach).
Is there any way to achieve this, or do I need to restructure dist/? The only other production TypeScript/Node.js project I've worked on is an Azure Function which leverages azure-functions-core-tools' func host start from dist/.

package.json scripts failing on heroku

So I have a series of scripts that are set up to either dev servers for a React/Node Express application OR a production server on heroku. The structure of the app is as follows:
client/package.json //pckg for react app
package.json //pckg for the node server
these are the scripts in the clients package:
"scripts": {
"start": "if-env NODE_ENV=production && npm run start:prod || npm run start:dev",
"start:prod": "node server.js",
"start:dev": "set NODE_ENV=development&& concurrently \"nodemon --ignore 'client/*'\" \"npm run client\"",
"client": "cd client && npm run start",
"seed": "node scripts/seedDB.js",
"install": "cd client && npm install",
"build": "cd client && npm run build",
"heroku-postbuild": "npm run build"
}
and the only difference between the react apps package.json and the one that is automatically generated with create-react-app is as follows:
"proxy": "http://localhost:3001/",
the way its supposed to run is, install scripts at root folder, run install script to cd into client and install react apps dependencies, then heroku's post-build script should kick in to run the build script which cds into client and builds a production ready react app. finally the start script should see a NODE_ENV of production and run start:prod.
my problem is that for some reason when i push to heroku, it seems to get stuck on an infinite loop on the install script. I have NO clue why, as the exact same scripts work on other projects PERFECTLY.
https://github.com/LordKriegan/reactdbdemo
https://github.com/LordKriegan/reactdbdemo2/ if anyone wants to look at it. (doing a full stack demo for my students :/ not much of a demo if i cant get it deployed)
I got it working. Forgot create-react-app also initializes a git repo...? either that or somewhere along the way i did an extra git init. anyways i had a .git folder in my client folder, which was preventing my client folder from being pushed up. i ended up creating a new repo and pushing everything to that one and now it works. so incase anyone comes here with a similar problem... make sure you didnt end up in some kind of gitception trap. :/

Package.json for server and client

I want to install package.json for client side from my server side package.json as the server side is using node and client side is using angular 2
directory structure
server-app
--bin
--node_modules
--package.json
--client-app
--app
--node_modules
--package.json
now the problem is:
I have to run this command npm install from server app folder and also from server-app/client-app folder separately this will create deployment issues
what I want is to run only one time npm install from i.e server-app and it will automatically install the server-app package.json and client-side-app
package.json too.
Any help will be highly appreciated
I think what you need is a npm module called concurrently.
With concurrently installed in your root folder you can run multiple custom npm scripts.
For example: you can create 2 separate scripts that are installing the dependencies (client-install and server-install) and then create install-all-deps script that will run both scripts one after another and install all deps in both directories.
{
"scripts": {
"client-install" : "cd client && npm install",
"server-install" : "cd server && npm install",
"install-all-deps": "concurrently \"npm run server-install\" \"npm run client-install\""
}
}
Here is the npm module https://www.npmjs.com/package/concurrently. Quoting doc:
Run multiple commands concurrently. Like npm run watch-js & npm run
watch-less but better.
Hope this helps.
Structure your application in the following way,
app
--server-app
--client-app
--node_modules
--package.json
This way you can have single package.json file

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"
},

Resources