Why am I getting 'Application Error' when deploying to Heroku? (MERN app) - heroku

I've checked the logs and this is what it says:
Here is my app.js file (at the root level):
// Importing frameworks, libraries, routes, and JSON parser
const express = require('express');
const mongoose = require('mongoose');
const rewards = require('./routes/api/rewards');
const bodyParser = require('body-parser');
const path = require('path');
// Loading static build folder for production
if (process.env.NODE_ENV === 'production') {
app.use(express.static('frontend/build'));
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, 'frontend', 'build', 'index.html'));
})
}
// Create a new Express server
const app = express();
// Setup middleware for body parser
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Import MongoDB key
const db = require('./config/keys').mongoURI;
// Connect to MongoDB using Mongoose
mongoose
.connect(db, {useNewUrlParser: true, useUnifiedTopology: true})
.then(() => console.log('Connected to MongoDB successfully'))
.catch(err => console.log(err));
// Create basic express routing
app.use('/api/rewards', rewards);
// Determining which port to run on
// Deploying on Heroku requires the server to be on process.env.PORT
const port = process.env.PORT || 5000;
// Start a socket and listen for connections on the path
// Display a success message when server is running correctly
app.listen(port, () => console.log(`Server is running on port ${port}`));
Any pointers/tips on what this error message is saying exactly? My best guess is that it has something to with one of my routes but I'm not too sure...

You are making your app variable below your if of production check to serve react build.
please move line
const app = express();
above your if check.
correct app.js would be:
// Importing frameworks, libraries, routes, and JSON parser
const express = require('express');
const mongoose = require('mongoose');
const rewards = require('./routes/api/rewards');
const bodyParser = require('body-parser');
const path = require('path');
// Create a new Express server
const app = express();
// Loading static build folder for production
if (process.env.NODE_ENV === 'production') {
app.use(express.static('frontend/build'));
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, 'frontend', 'build', 'index.html'));
})
}
// Setup middleware for body parser
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Import MongoDB key
const db = require('./config/keys').mongoURI;
// Connect to MongoDB using Mongoose
mongoose
.connect(db, {useNewUrlParser: true, useUnifiedTopology: true})
.then(() => console.log('Connected to MongoDB successfully'))
.catch(err => console.log(err));
// Create basic express routing
app.use('/api/rewards', rewards);
// Determining which port to run on
// Deploying on Heroku requires the server to be on process.env.PORT
const port = process.env.PORT || 5000;
// Start a socket and listen for connections on the path
// Display a success message when server is running correctly
app.listen(port, () => console.log(`Server is running on port ${port}`));

Related

Discord.js v.13.3.1:guildmemberadd event not working

I recently updated my discord.js version from v12 to v13.3.1 and the 'guildMemberAdd' event stopped working, although I enabled PRESENCE INTENT as well as SERVER MEMBERS INTENT on my application.
const Discord = require('discord.js');
const client = new Discord.Client({ intents: [Discord.Intents.FLAGS.GUILD_MESSAGES, Discord.Intents.FLAGS.GUILDS] });
client.once('ready', () => {
console.log(client.user.tag + ' is online!');
});
client.on("guildMemberAdd", guildMember => {
let welcomeRole = guildMember.guild.roles.cache.find(role => role.name === 'member');
guildMember.roles.add(welcomeRole);
});
const client = new Client({ intents: [Intents.FLAGS.GUILDS ,Intents.FLAGS.GUILD_MESSAGES,Intents.FLAGS.GUILD_MEMBERS] });
https://discord.com/developers/applications

How to access privateRuntimeConfig declared in Nuxt.config.js in serverMiddleware?

How to access configuration declared in privateRuntimeConfig in Nuxt.config.js file in serverMiddleware?
$config and context are not available in serverMiddleware.
I am using serverMiddleware in Nuxtjs to write api.
Its getting called however I am trying to pass some configuration from privateRuntimeConfig in Nuxt.config.js file.
const bodyParser = require('body-parser')
const app = require('express')()
const { uuid } = require('vue-uuid')
const productsModule = require('../lib/bal/products')
app.use(bodyParser.json())
app.post('/create', (req, res) => {
console.log('Config:' + String(req))
const result = productsModule.createProduct(this.$config, req.body.name, 'Trial product', '', 10, false, uuid.v1)
if (result === undefined) {
res.status(500).json({ error: 'Failed to create product. Try again!' })
return
}
console.log(result)
res.status(200).json(result)
})
module.exports = app
Yes you are right, since serverMiddleware only runs at service-side you can't use this.$config or context.$config.
What i did is, if it is a static data, i use environment variables to call the data.
.env file
APP_USERNAME=M457ERCH1EF
serverMiddleware file i.e xxx.js
....
const username = process.env.APP_USERNAME
....

How to deploy next.js 9 to AWS Lambda without using Serverless Components

I would like to simply deploy my Next.js 9 to AWS Lambdas using just API Gateway in front and make a proxy to the static path pointing to S3, but the only available option (without having to write all the stuff from the scratch) is https://github.com/serverless-nextjs/serverless-next.js which is currently using a beta version of Serverless Components (very buggy and lack of control over resources created as it does not uses CloudFormation), also this SLS Component forces the user to use CloudFront which is not my need, I have PR environments created all the time and allocating CloudFront for that is just waste of time/money/resources.
I tried to use the old version of the plugin serverless-nextjs-plugin but it seems not to work with Next.js 9, it fails to create the Lambdas for .html generated pages.
Is there any light in the end of this tunnel?
https://github.com/serverless-nextjs/serverless-next.js/issues/296 by this issue it looks like there's no way to do that.
I managed to make it work
serverless.base.yml file:
service: my-app
provider:
name: aws
runtime: nodejs12.x
timeout: 10 # seconds
memorySize: 1792 # Mb
custom:
webpack:
packager: yarn
includeModules:
forceInclude:
- chalk
functions:
nextJsApp:
handler: server.handler
events:
- http: 'ANY /'
- http: 'ANY {proxy+}'
server.js:
const { parse } = require('url');
const next = require('next');
const serverless = require('serverless-http');
const app = next({
dev: false
});
const requestHandler = app.getRequestHandler();
export const handler = serverless(async (req, res) => {
const parsedUrl = parse(req.url, true);
await requestHandler(req, res, parsedUrl);
});
wepback.config.js:
const CopyWebpackPlugin = require('copy-webpack-plugin');
const nodeExternals = require('webpack-node-externals');
module.exports = {
...
externals: [nodeExternals()],
plugins: [
new CopyWebpackPlugin({
patterns: [
{ from: '.next', to: '.next' },
{ from: 'public', to: 'public' }
]
})
]
};
and here is the trick for working with serverless and webpack, use a serverless.js that modifies the serverless.base.yml and add all dependencies to the required dependencies to be included in the bundle:
const yaml = require('yaml-boost');
const minimist = require('minimist');
const path = require('path');
module.exports = (() => {
const params = minimist(process.argv.slice(2));
const serverless = yaml.load(path.join(__dirname, 'serverless.base.yml'), params);
const packageJson = require(path.join(__dirname, 'package.json'));
const dependencies = Object.keys(packageJson.dependencies);
serverless.custom.webpack.includeModules.forceInclude.push(...dependencies);
return serverless;
})();

import/export in Typescript

I have an existing Node.js (Node only, no Typescript) application with the following files (generated by Visual Studio Node template):
In file app.js:
var express = require("express");
var app = express();
...
module.exports = app;
In file socket.js:
module.exports = function (server,app) {
// ....
}
In file www:
var app = require("../app");
var server = app.listen(app.get(8081), function() {
});
var sockets = require("../routes/sockets")(server, app);
I am no migrating it to Typescript. How do I convert the above export/require to the equivalent in Typescript?
Where can I find the proper specifications of the import and export keywords? I am unable to find documentation of what they mean and do exactly. I do see many examples of some permutations of their usage.
To ensure that your import statements will be transpiled into require(), you need to specify that you want to use commonjs modules during the TypeScript compilation. Here's an example of tsconfig.json:
{
"compilerOptions": {
"module": "commonjs",
"outDir": "build",
"target": "es5"
}
}
Here's an example of the Node/Express server in TypeScript:
import * as express from "express";
const app = express();
app.get('/products', (req, res) => res.send('Got a request for products'));
const server = app.listen(8000, "localhost", () => {
const {address, port} = server.address();
console.log('Listening on %s %s', address, port);
});

REST API with koa2. Common prefix for several routers

I have two entities, users and employees. So I want CRUD for both in different endpoints, but both of them will be mounted under "api", so I can define api_v1, api_v2 and so on.
The endpoints would be something like:
get api/users
put api/users/12
delete api/users/12
get api/employees
....
I can't get "api" prefix for both of my routes. Can't get it working with koa-mount.
My files:
server.js
// Dependencies
import Koa from 'koa'
import mongoose from 'mongoose'
import logger from 'koa-logger'
// import parser from 'koa-bodyparser';
import convert from 'koa-convert'
import serve from 'koa-static'
import Router from 'koa-router'
import session from 'koa-generic-session'
import mount from 'koa-mount'
// A seperate file with my routes.
import routingUsers from './users'
import routingEmployees from './employees'
// config
const config = require("./config/config")
// connect to the database
mongoose.connect(config.mongo.url)
mongoose.connection.on('error', console.error)
// Creates the application.
const app = new Koa()
// how to use koa-mount to make this work? Arghhhhh!
// const api = new Koa();
// api.use(convert(mount ('/api', app)))
// trust proxy
app.proxy = true
// sessions
app.keys = ['your-session-secret']
// Applies all routes to the router.
const user = routingUsers(Router())
const employee = routingEmployees(Router())
app
.use(logger()) // log requests, should be at the beginning
.use(user.routes()) // asign routes
.use(employee.routes()) // asign routes
.use(user.allowedMethods())
.use(employee.allowedMethods())
.use(convert(session())) // session not needed for an API??????
.use(convert(serve(__dirname + '/public'))) // for static files like images
// Start the application.
app.listen(3000, () => console.log('server started 3000'))
export default app
users.js (employees.js is the same).
// Export a function that takes the router
export default router => {
// Set a prefix of our api, in this case locations
const api = 'users'
router.prefix(`/${api}`);
// GET to all locations.
router.get('/', (ctx, next) =>
ctx.body = 'hello users');
// ctx.body = await Location.find());
// POST a new location.
router.post('/', async (ctx, next) =>
ctx.body = await new Location(ctx.request.body).save());
// Routes to /locations/id.
router.get('/:id', async (ctx, next) =>
ctx.body = await Location.findById(ctx.params.id));
// PUT to a single location.
router.put('/:id', async (ctx, next) =>
ctx.body = await Location.findByIdAndUpdate(ctx.params.id, ctx.body));
// DELETE to a single location.
router.delete('/:id', async (ctx, next) =>
ctx.body = await Location.findByIdAndRemove(ctx.params.id));
return router;
}
I use the following solution:
import Router from 'koa-router';
const router = new Router()
.get('/', function(ctx) {
ctx.body = 'Index';
});
const apiRouter = new Router({
prefix: '/api'
})
.get('/templates', Templates.index)
.post('/templates', Templates.store)
.put('/templates', Templates.update)
.get('/lists', Lists.index);
router.use(apiRouter.routes());
Finally I've sent another parameter to the routers modules, so I used router prefix:
// Applies all routes to the router.
const user = routingUsers(Router(), 'api/users/')
const employee = routingEmployees(Router(), 'api/employees/')
Users would be:
export default (router, prefix) => {
// Set a prefix of our api, in this case locations
// const api = 'users'
router.prefix(`/${prefix}`);
....

Resources