Full-Stack Heroku App In 3 Minutes

LEAN Stack — No New Frameworks

Samuel Brice
4 min readFeb 25, 2018

Previouly: LEAN Stack — No New Frameworks

In this tutorial we’ll build a LEAN app and deploy it to Heroku.

The philosophy is about not creating anything “new.” We’re leveraging mature starter kits from Nest and Angular, integrating them with minimal overhead. This enables us to focus on the core product while easily staying in sync with the technology.

TLDR Instructions

Deploy to Heroku

git clone https://github.com/sbrice/lean-starter lean-starter
cd lean-starter
heroku create
heroku config:set NPM_CONFIG_PRODUCTION=false
git push heroku master
heroku open

Develop on Local

git clone https://github.com/sbrice/lean-starter lean-starter
cd lean-starter
npm run install
npm run start:dev

Step-by-Step Instructions

1. Setup Project

In your root project directory create a package.json with no dependencies:

npm init

2. Add Server and Client Submodules

Fork the Nest Typescript Starter and the Angular Starter then add them as submodules into separate ./server and ./client directories:

git submodule add https://github.com/sbrice/typescript-starter.git servergit submodule add https://github.com/sbrice/angular-starter.git client

3. Create NPM Scripts

To mix the Client and Server submodules we’ll purely be using NPM Scripts.

Inside your ./package.json add scripts to install and start your app:

...“scripts”: {
"install": "npm run install:client && npm run install:server",
"install:client": "(cd ./client && npm install)",
"install:server": "(cd ./server && npm install)",
"start": "npm run start:dev",
"start:dev": "npm run start:client & npm run start:server",
"start:client": "(cd ./client && npm run start)",
"start:server": "(cd ./server && npm run start:watch)"
},
...

3. Configure Separate Ports

Configure Nest and Angular to run on separate ports.

Modify ./server/src/main.ts:

import { NestFactory } from '@nestjs/core';
import { ApplicationModule } from './app.module';
const NEST_PORT = process.env.PORT || 3000;async function bootstrap() {
const app = await NestFactory.create(ApplicationModule);
await app.listen(NEST_PORT);
}
bootstrap();

Modify ./client/config/webpack.dev.js:

...const ENV = process.env.ENV = process.env.NODE_ENV = 'development';
const HOST = process.env.HOST || 'localhost';
const NEST_PORT = process.env.PORT || 3000;
const PORT = process.env.CLIENT_PORT || 3500;
const METADATA = Object.assign({}, buildUtils.DEFAULT_METADATA, {
host: HOST,
port: PORT,
nestPort: NEST_PORT,
ENV: ENV,
HMR: helpers.hasProcessFlag('hot'),
PUBLIC: process.env.PUBLIC_DEV || HOST + ':' + PORT
});
...

4. Proxy to Nest Sever from Angular DevServer

Add DevServer proxy to the Nest server for all requests starting with /api.

Doesn’t necessarily need to be /api — that’s just my preference.

Modify ./client/config/webpack.dev.js:

...devServer: {
...
proxy: [{
context: ['/api'],
target: `
http://${METADATA.host}:${METADATA.nestPort}`
}],
...},...

5. Serve Built Client Files from Nest Server

Modify ./server/src/main.ts:

import * as express from 'express';
import { join } from 'path';

import { NestFactory } from '@nestjs/core';
import { ApplicationModule } from './app.module';
const SERVER_PORT = process.env.PORT || 3000;
const CLIENT_FILES = join(__dirname, '..', '..', 'client', 'dist');
async function bootstrap() {
const app = await NestFactory.create(ApplicationModule);
app.use(express.static(CLIENT_FILES));
await app.listen(SERVER_PORT);
}
bootstrap();

6. Add Prod and Build Scripts

Add start:prod and build scripts to your ./package.json

...“scripts”: {
"install": "npm run install:client && npm run install:server",
"install:client": "(cd ./client && npm install)",
"install:server": "(cd ./server && npm install)",
"postinstall":"npm run build",
"build": "npm run build:client",
"build:client": "(cd ./client && npm run build)",
"start": "npm run start:prod",
"start:prod": "(cd ./server && ./node_modules/.bin/ts-node ./src/main.ts)",

"start:dev": "npm run start:client & npm run start:server",
"start:client": "(cd ./client && npm run start)",
"start:server": "(cd ./server && npm run start:watch)"
},
...

7. Create and Push to Heroku

At this point your git status should look something like:

Create your Heroku app as normal and set NPM_CONFIG_PRODUCTION=false for Heroku to install devDependencies.

This is a personal preference as it allows running the app with ts-node.

heroku create
heroku config:set NPM_CONFIG_PRODUCTION=false

Our final step is to add, commit, then push to Heroku.

git submodule foreach git commit -am 'Chemical X'
git submodule foreach git push origin master
git add .
git commit -am 'LEAN - Init'
git push origin master
git push heroku master
heroku open

--

--

Samuel Brice
Samuel Brice

Written by Samuel Brice

This page intentionally left blank.

No responses yet