Skip to content

Instantly share code, notes, and snippets.

@eiriklv
Last active Apr 26, 2018
Embed
What would you like to do?
Tommy

Faster Biker Oslo

tl;dr

Development:

clone this repo
yarn install
make .env file from example.env
yarn run dev
(automatically) open browser at localhost:3000
🚀

The config variables can be found in the Heroku settings for each app. Due to create-react-app variables needs to be prefixed with REACT_APP to be exposed in the React (client-side) app.

This application base hosts all of the apps in the system:

  • Frontend /src/frontend
  • API /src/api

📦 Tech

💻 Deploy

Heroku Multi Procfile Buildpack

Set the following environment variables to specify which app you want to deploy:

  • PROCFILE
    • Set the path to the Procfile you want to use
    • Example: ./src/frontend/Procfile
  • APP
    • Set the name of the app you are deploying
    • Corresponding to its folder name
    • Makes sure the correct scripts are executed
    • Example: frontend

Then set the additional appropriate environment variables that are required by the application specified.

📚 Overview

TODO

/**
* Dependencies
*/
const spawn = require('cross-spawn');
/**
* Package.json
*/
const packageJson = require('../package.json');
/**
* Get the specified app from the environment
*/
const APP = process.env.APP;
/**
* Abort of no app specified
*/
if (!APP) {
console.log('No APP specified - skipping build step')
process.exit();
}
/**
* Get appropriate build script
*/
const buildScript = packageJson.scripts[`${APP}:build`];
/**
* Abort if invalid app specified
*/
if (!buildScript) {
throw new Error('Non-existing APP specified - either you forgot to set the environment variable or you made a typo!')
}
/**
* Run build script for the specified app
*/
const build = spawn('npm', ['run', `${APP}:build`], {
stdio: 'inherit'
});
build.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
{
"name": "mm-challenge",
"version": "0.3.0",
"private": true,
"dependencies": {
"array-includes": "^3.0.2",
"auto-bind": "0.1.0",
"axios": "^0.15.3",
"babel-cli": "^6.23.0",
"babel-core": "^6.23.1",
"babel-polyfill": "^6.23.0",
"babel-preset-es2015": "^6.22.0",
"babel-preset-stage-0": "^6.22.0",
"basic-auth": "^1.1.0",
"body-parser": "^1.17.0",
"cachegoose": "^3.0.2",
"clamp": "^1.0.1",
"compression": "^1.6.2",
"concurrently": "^3.4.0",
"connect-history-api-fallback": "^1.3.0",
"cors": "^2.8.1",
"cross-spawn": "^5.1.0",
"date-fns": "^1.28.5",
"dotenv": "^4.0.0",
"express": "^4.15.0",
"force-ssl-heroku": "^1.0.2",
"helmet": "^3.5.0",
"jsonwebtoken": "^7.3.0",
"lodash": "^4.17.4",
"mime-types": "^2.1.15",
"mongoose": "^4.8.6",
"nodemon": "^1.11.0",
"qs": "^6.4.0",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-redux": "^5.0.3",
"react-router": "^3.0.2",
"react-router-redux": "^4.0.8",
"react-scripts": "0.9.3",
"react-scrollable-anchor": "^0.4.2",
"react-select": "^1.0.0-rc.3",
"react-youtube": "^7.3.0",
"redis-url": "^1.2.1",
"redux": "^3.6.0",
"redux-saga": "^0.14.3",
"reselect": "^2.5.4",
"sanitize.css": "^5.0.0",
"sort-by": "^1.2.0",
"styled-components": "^1.4.4"
},
"scripts": {
"cloud:start": "node ./scripts/start.js",
"cloud:build": "node ./scripts/build.js",
"frontend:dev": "react-scripts start",
"frontend:start": "node ./src/frontend/server.js",
"frontend:build": "node ./node_modules/react-scripts/bin/react-scripts.js build",
"backend:dev": "nodemon ./src/backend/start.js",
"backend:start": "node ./src/backend/start.js",
"backend:build": "echo \"no build required\"",
"dev": "concurrently \"npm run frontend:dev\" \"npm run backend:dev\"",
"start": "npm run cloud:start",
"build": "concurrently \"npm run frontend:build\" \"npm run backend:build\"",
"postinstall": "npm run cloud:build",
"test": "node ./node_modules/react-scripts/bin/react-scripts.js test --env=jsdom",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"engines": {
"node": "7.7.1"
},
"babel": {
"presets": [
"es2015",
"stage-0"
]
}
}
/**
* Dependencies
*/
import express from 'express';
import cors from 'cors';
import bodyParser from 'body-parser';
/**
* Create our express app
*/
const app = express();
/**
* Enable CORS
*
* TODO: Enable this only for the applicable domains in production
*/
app.use(cors());
/**
* Enable JSON body parsing
*/
app.use(bodyParser.json());
/**
* Health check
*/
app.get('/', (req, res) => {
res.send('hello world');
});
/**
* Attach server to port
*/
app.listen(port, () => {
console.log(`API listening to port ${port}`);
});
/**
* Dependencies
*/
const spawn = require('cross-spawn');
/**
* Package.json
*/
const packageJson = require('../package.json');
/**
* Get the specified app from the environment
*/
const APP = process.env.APP;
/**
* Get appropriate start script
*/
const startScript = packageJson.scripts[`${APP}:start`];
/**
* Run start script for the specified app
*/
if (startScript) {
const start = spawn('npm', ['run', `${APP}:start`], {
stdio: 'inherit'
});
start.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
}
/**
* Load environment vars from .env
*/
require('dotenv').config();
/**
* Enable ES2016+
*/
require('babel-polyfill');
require('babel-register');
/**
* Initialize application
*/
require('./server');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment