Full-Stack Heroku App In 3 Minutes
LEAN Stack — No New Frameworks
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