Issue running Next.js on iisnode on Azure Web App - node.js

Trying to deploy and run Next.js on Azure Web App. Azure Web App works when running just with Express.js but as soon as I call nex() it fails. Tried to enable the error logging in Azure portal but not much of any use came out, just generic 500 errors.
Below is what works and what doesn't.
Works:
var express = require('express');
var expressServer = express();
expressServer.get('/', function (req, res) {
res.send('Express is working on IISNode!');
});
expressServer.listen(process.env.PORT || 8080);
Does not work:
var express = require('express');
const next = require('next');
var expressServer = express();
var app = next();
expressServer.get('/', function (req, res) {
res.send('Express is working on IISNode!');
});
expressServer.listen(process.env.PORT || 8080);
I don't even bother getting request handler at this point as the app = next() is failing.
Package.json:
"engines": {
"node": "9.4.0 || 8.9.x"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.16.2",
"next": "^4.2.3",
"next-redux-wrapper": "^1.3.5",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-redux": "^5.0.6",
"redux": "^3.7.2",
"redux-thunk": "^2.2.0"
},
"devDependencies": {
"babel-preset-es2015": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"nodemon": "^1.14.11"
}
EDIT:
I believe the issue is that next build needs to run first. I am looking if I can add some post deployment/build command with something like Kudu. If you have any suggestions please let me know.

You are right, you need to run next build first.
So, this would work in Azure Web App if you create pages directory under project root and edit the package.json to add this:
"scripts": {
"postinstall": "next build"
}

Related

Deployment of Express application on Heroku Error : Cannot find module '/app/server.js'

I've been trying to deploy my Express application on Heroku and the build gets created successfully but when I try to open it, I'm greeted with an error message that basically states that the page could not be served.
So, I run heroku logs --tail and then I get the following error messages :
One half of the error messages
Remaining half of the error messages
File Tree
Procfile
web: node server.js
Package.json
{
"name": "conduit-api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.0.1",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"nodemon": "^2.0.12",
"pg": "^8.7.1",
"pg-hstore": "^2.3.4",
"redux-persist": "^6.0.0",
"sequelize": "^6.6.5"
},
"devDependencies": {
"cross-env": "^7.0.3"
}
}
server.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const { sequelize } = require('./src/entities/User/User');
const db = require('./src/config/Database');
const feedRoute = require('./src/routes/Feed/Feed');
const usersRoute = require('./src/routes/Users/Users');
const userRoute = require('./src/routes/User/User');
const articlesRoute = require('./src/routes/Articles/Articles');
const profilesRoute = require('./src/routes/Profiles/Profiles');
const commentsRoute = require('./src/routes/Comments/Comments');
const app = express();
app.use(cors());
app.use(bodyParser.json());
// Routes
app.use('/api/feed', feedRoute);
app.use('/api/users', usersRoute);
app.use('/api/user', userRoute);
app.use('/api/articles', articlesRoute);
app.use('/api/profiles', profilesRoute);
app.use('/api/articles', commentsRoute);
// REQUESTS
app.get('/', async (req,res) => {
res.json('Yooooooooooo')
try {
await db.authenticate();
console.log('Connection has been established');
} catch(err) {
console.log('Error');
}
})
// To START sequelize and also wipes the DB clean
// async function main() {
// await sequelize.sync({force: true})
// }
// main()
// TO START sequelize
const PORT = process.env.PORT || 3000;
app.listen(PORT , () => {
console.log(`App is listening to ${PORT}`);
})
I've tried modifying my procfile and removing and re-installing the modules but the problem still persists.
I've been stuck on this for days now and any sort of help would be highly appreciated.
Looks like you problem is your pointing the main in package.json to a file that doesn't exist.
Package.json
"main": "index.js"
Your app seems to deploy from you server.js file.
The main field is a module ID that is the primary entry point to your program.
as per documentation: https://docs.npmjs.com/cli/v7/configuring-npm/package-json#main

Webpack not detecing proxy for local development

I'm having trouble getting a little proxy working with my React app. I'm trying to use a little express server to keep some API keys secret so that my application can make use of a 3rd party API (the github API to be specific). I have a small express app running that I can query to get the API keys out of a .env file and attach those keys to my request to the 3rd party API.
Presently, I am able to start the front-end application and the express app simultaneously, and I can query the express app and get a response using my browser.
I'm trying to configure webpack to proxy my requests through this express app. In my webpack.config.js file I have:
//
devServer: {
port: 8080,
proxy: {
'/api/**': {
target: 'http://localhost:3000',
secure: false,
changeOrigin: true
}
}
}
//
Front-end application is running on port 8080, and my Express app is running on port 3000, both on the localhost.
In my React App, for trying to test whether this proxy is being detected/used, I have the following in a component:
//
handleSubmit(event) {
event.preventDefault();
fetch('/api/secret')
.then(res => {
console.log('RES: ', res)
res.json()
})
.then(data => {
console.log("Data: ", data)
return JSON.stringify(data)
})
this.props.onSubmit(this.state.username)
}
//
The backend code is super simple at the moment, but here it is:
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
require('dotenv').config();
// Initialize app
const app = express();
const port = 3000;
// Configure
app.use(bodyParser.json())
app.use(cors())
app.get('/secret', (req, res) => {
res.status(200)
res.send({ aSecret: process.env.<API_KEY> })
})
app.listen(port, () => console.log(`App is running on port ${port}`))
In my package.json I have the following (relevant script and dependencies):
...
...
"start": "concurrently --kill-others \"webpack-dev-server\" \"npm run server\"",
"server": "nodemon server/index.js"
},
"babel": {
"presets": [
"#babel/preset-env",
"#babel/preset-react"
]
},
"dependencies": {
"prop-types": "^15.7.2",
"react": "^16.13.0",
"react-dom": "^16.13.0",
"react-icons": "^3.9.0"
},
"devDependencies": {
"#babel/core": "^7.8.7",
"#babel/preset-env": "^7.8.7",
"#babel/preset-react": "^7.8.3",
"babel-loader": "^8.0.6",
"body-parser": "^1.19.0",
"concurrently": "^5.1.0",
"cors": "^2.8.5",
"css-loader": "^3.4.2",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"html-webpack-plugin": "^3.2.0",
"nodemon": "^2.0.2",
"style-loader": "^1.1.3",
"svg-inline-loader": "^0.8.2",
"webpack": "^4.42.0",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3"
},
"proxy": "http://localhost:3000"
}
As you can see, in the component I'm (attempting to) making a request to api/secret and hoping to get back in the response the API key that I have stored in my .env.
When I query this route in my browser using fetch('http://localhost:3000/secret') I am able to access the API key successfully, so I know that when I run the npm run start script that both the React application and the Express application are starting up simultaneously.
When I click the button in my React component that sends a request to /api/secret I get the following output in the browser console (in keeping with the console logs I have in the react component at the moment):
I'm just not sure at this point what I'm doing wrong with the proxy configuration in the devServer webpack configuration.
I can see that the hostname is being automatically prepended to the /api/secret in the fetch within the React component.
Stated Goal: Webpack successfully detects the proxy server I'm using to server requests to the 3rd party (GitHub) API.
I apologize if this question is a repeat, I've spent several hours researching and fiddling with this configuration and have been unsuccessful in finding out how to configure this. This is my first attempt at spinning up a little proxy server as well. Thanks in advance for any help!
You need to return res.json()
handleSubmit(event) {
event.preventDefault();
fetch('/api/secret')
.then(res => {
console.log('RES: ', res)
return res.json()
})
.then(data => {
console.log("Data: ", data)
return JSON.stringify(data)
})
this.props.onSubmit(this.state.username)
}

Status Code: 405 Not Allowed in React frontend hosted on Heroku

I have made an app in react frontend and express as backend framework. These both are working fine in my local computer and when I have hosted Both server and client in Heroku they are deployed properly but when I am trying to login I am getting 405: Not allowed error.
When I am using the same server hosted in Heroku with the frontend hosted in my desktop it is working fine.
client : https://calm-fjord-20606.herokuapp.com/login
server : https://recorder-server-pkr.herokuapp.com/user/login
I have gone through many of the solutions provided here and in GitHub but none of them clarified my doubt.
/server.js - server
const express = require("express");
var app = express();
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const db = require("./config/keys").mongoURI;
const passport = require("passport");
const cors = require("cors");
mongoose
.connect(db, { useNewUrlParser: true })
.then(() => {
console.log("Mongoose connected");
})
.catch(err => console.log(err));
//body-parser
app.use(bodyParser.urlencoded({ extended: true }));
// parse application/json
app.use(bodyParser.json());
//passport middleware
app.use(passport.initialize());
var publicDir = require("path").join(__dirname, "/public");
app.use(express.static(publicDir));
//routes
require("./routes/api/user")(app);
require("./routes/verifyaccount")(app);
require("./routes/api/file")(app);
app.get("/", cors(),(req, res) => {
res.json({
post: {
"/user/register": "to register",
"/user/login": "to login",
"/file": "to upload file",
"/verifyaccount/email": "to verify email using otp",
"/verifyaccount/sms": "to verify sms otp",
"/sendVerificationCode": "to reset password or resend verification code",
"/reset/:secretToekn": "forgot password"
},
get: {
"/current": "current user",
"/file": "to fetch file"
}
});
});
//passport config
require("./config/passport")(passport);
const port = process.env.PORT || 5000;
app.listen(port, process.env.IP , () => {
console.log(`Server started at port ${port}`);
});
/package.json - from client
{
"name": "light-bootstrap-dashboard-react",
"version": "1.2.0",
"private": true,
"dependencies": {
"axios": "^0.18.0",
"bootstrap": "3.3.7",
"chartist": "^0.10.1",
"classnames": "^2.2.6",
"draft-js": "^0.10.5",
"draftjs-to-html": "^0.8.4",
"griddle-react": "^1.0.0",
"history": "^4.7.2",
"html-to-draftjs": "^1.4.0",
"jquery": "^3.4.1",
"jspdf": "^1.5.3",
"jwt-decode": "^2.2.0",
"lodash": "^4.17.11",
"mdbreact": "^4.15.0",
"moment": "^2.24.0",
"node-sass": "4.6.1",
"node-sass-chokidar": "0.0.3",
"npm-run-all": "4.1.2",
"react": "^16.8.4",
"react-bootstrap": "0.32.1",
"react-bootstrap-table-next": "^3.0.1",
"react-chartist": "^0.13.1",
"react-dom": "^16.8.4",
"react-draft-wysiwyg": "^1.13.2",
"react-google-maps": "9.4.5",
"react-notification-system": "0.2.17",
"react-redux": "^6.0.1",
"react-router-dom": "^4.3.1",
"react-scripts": "^2.1.8",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0"
},
"scripts": {
"build-css": "node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar --include-path ./src --include-path ./node_modules src/ -o src/ --watch --recursive",
"start-js": "react-scripts start",
"start": "npm-run-all -p watch-css start-js",
"build": "npm run build-css && react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"proxy": "https://recorder-server-pkr.herokuapp.com",
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
Any help will be appreciated. Thank you
Use cors middleware on server.
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
There are two ways:
You must enable cors in Back-end. (You can search Google as cors express )
You can use proxy in Front-end

Proxy Routing on Angular App deployed on Heroku

I have an Angular app that is talking to a REST service.
When I run the Angular app local with the CLI, correctly proxies all /api requests to the REST service. When I try to build the app and run through a server.js (so that I can deploy the app to Heroku) I lose the proxy routing.
The REST service is deployed on Heroku and runs fine.
I run the Angular with:
ng serve
My proxy.conf.json
{
"/api": {
"target": "https://my-app.herokuapp.com",
"secure": true,
"changeOrigin": true
}
}
I created a server.js as described in this article so that I can deploy onto Heroku.
// server.js
const express = require('express');
const app = express();
const path = require('path');
// If an incoming request uses
// a protocol other than HTTPS,
// redirect that request to the
// same url but with HTTPS
const forceSSL = function () {
return function (req, res, next) {
if (req.headers['x-forwarded-proto'] !== 'https') {
return res.redirect(
['https://', req.get('Host'), req.url].join('')
);
}
next();
}
}
// Instruct the app
// to use the forceSSL
// middleware
app.use(forceSSL());
// Run the app by serving the static files
// in the dist directory
app.use(express.static(__dirname + '/dist'));
// For all GET requests, send back index.html
// so that PathLocationStrategy can be used
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname + '/dist/index.html'));
});
// Start the app by listening on the default
// Heroku port
app.listen(process.env.PORT || 4200);
I also set up a post install build in my package.json scripts:
{
"name": "catalog-manager-client",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "node server.js",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"postinstall": "ng build --aot"
},
"private": true,
"dependencies": {
"#angular/animations": "^6.0.3",
"#angular/cdk": "^6.2.1",
"#angular/cli": "~6.0.8",
"#angular/language-service": "^6.0.3",
"#angular/common": "^6.0.3",
"#angular/compiler": "^6.0.3",
"#angular/compiler-cli": "^6.0.3",
"#angular/core": "^6.0.3",
"#angular/flex-layout": "^6.0.0-beta.16",
"#angular/forms": "^6.0.5",
"#angular/http": "^6.0.3",
"#angular/material": "^6.2.1",
"#angular/platform-browser": "^6.0.3",
"#angular/platform-browser-dynamic": "^6.0.3",
"#angular/router": "^6.0.3",
"#swimlane/ngx-charts": "^8.0.2",
"#swimlane/ngx-datatable": "^13.0.1",
"core-js": "^2.5.4",
"express": "^4.16.4",
"hammerjs": "^2.0.8",
"jquery": "^3.3.1",
"moment": "^2.22.2",
"ngx-perfect-scrollbar": "^6.2.0",
"ngx-quill": "^3.2.0",
"rxjs": "^6.0.0",
"rxjs-compat": "^6.2.1",
"rxjs-tslint": "^0.1.4",
"zone.js": "^0.8.26"
},
"devDependencies": {
"#angular-devkit/build-angular": "~0.6.8",
"typescript": "~2.7.2",
"#types/jasmine": "~2.8.6",
"#types/jasminewd2": "~2.0.3",
"#types/node": "~8.9.4",
"codelyzer": "~4.2.1",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~1.7.1",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.0",
"karma-jasmine": "~1.1.1",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.3.0",
"ts-node": "~5.0.1",
"tslint": "~5.9.1"
},
"engines": {
"node": "9.11.2",
"npm": "6.5.0"
}
}
I am an Angular novice so I could be making a fundamental mistake, but how do I modify the server.js to use the proxy.conf.json settings?
The explanation falls into the yes, you're making a fundamental mistake category, but I've seen enough similar questions that I thought an explanation might just help the next dev.
The Angular CLI is running a full http server. The Angular UI is fully compiled and the CLI is serving it as static content from the /dist directory.
The proxy.conf.json settings are for the Server run by the Angular CLI, it has nothing to do with your compiled code.
When you move from a local environment to something like Heroku you need a server to take the place of the Angular CLI. This is where all the examples of node.js and express come in. The simple server.js file they walk you through is enough to set up a basic static content server. And that's fine, because your Angular code is static content!
But if you need routing to a dynamic backend server via a proxy.conf.json, well, your simple static server doesn't know anything about that.
In my case, my backend server runs on Koa, so I added static routing to the Angular code.
const router = require('koa-router')();
const body = require('koa-body')({ text: false });
const send = require('koa-send');
const fs = require('fs');
/**
* Code about server routes ommited
*/
async function main(ctx, next) {
//All dynamic routes start with "/api"
if (/\/api\//.test(ctx.path)) {
try {
await next();
}
catch (error) {
if (error instanceof ApplicationError) {
logger.error(error, { data: error.data, stack: error.stack });
ctx.status = error.code;
} else {
ctx.status = 500;
logger.error(error.message, { stack: error.stack });
}
}
return;
} else {
//Not a dynamic route, serve static content
if ((ctx.path != "/") && (fs.existsSync('dist' + ctx.path))) {
await send(ctx, 'dist' + ctx.path);
} else {
await send(ctx, 'dist/index.html');
}
}
}
module.exports = app => {
app.use(main);
app.use(router.routes());
};
NOTE - this isn't a performant solution for any kind of high workload, but if you've got a very small project that doesn't justify spending resources setting up something more scalable, this will work until you get bigger.
Any One looking for Implementation of angular application using proxy api on heroku you can use WebpackDev Server and http-proxy-middleware in server.js
npm install http-proxy-middleware
npm install webpack webpack-dev-server
webpack.config.js
const path = require('path');
module.exports = {
entry:'./src/index.js',//no implemenation needed by default webpack verification
mode: 'development',
devServer: {
historyApiFallback: true,// handle 404 cannot get error after refreshing url
https: true,//secure the server
compress: true,//invalid header multiple url proxy
client: {
webSocketURL: 'ws://0.0.0.0:8080/ws',// handle Invalid header error in heroku port 8080 maps in server.js
},
static: {
directory: path.join(__dirname, '/dist/<app-name>'),
},
proxy: {
/** Same as proxy.conf.json or proxy.conf.js */
' /api1/*': {
target: 'https://<other-heroku-deployed-url>',
changeOrigin:true,
secure:false,
pathRewrite: {
'^/api1':'https://<other-heroku-deployed-url>/api1' },
},
' /api2/*': {
target: 'https://<other-heroku-deployed-url>',
changeOrigin:true,
secure:false,
pathRewrite: {
'^/api2':'https://<other-heroku-deployed-url>/api2' },
}
},
},
};
server.js
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
const Webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
/** this is custom js to help proxy in server.js*/
const webpackConfig = require('./webpack.config.js');
const compiler = Webpack(webpackConfig);
const devServerOptions = { ...webpackConfig.devServer, open: true };
const server = new WebpackDevServer(devServerOptions, compiler);
const runServer = async () => {
console.log('Starting server...');
await server.start();
};
runServer();
/** If you have error creating proxy <app-url> to localhost
* Heroku internally redirect the Server port 8080 .
* For that reason we need to open listener port(I used 3000 here) redirect
through http-proxy-middleware*/
app.use("/*", createProxyMiddleware(
{ target: "https://localhost:8080",
ws: true ,
changeOrigin: true,
secure:false,
router: {
'dev.localhost:3000': 'https://localhost:8080',
},}))
app.listen(process.env.PORT || 3000)
npm start or node server.js

Heroku Deployment Nodejs

I developed a app using react, mongodb, express, nodeJS. I am able to run the app perfectly in my desktop. I have run express & react on different ports. But this doesn't work when I deploy it to heroku.
server.js
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
var Schema = mongoose.Schema;
var session = require('express-session');
var cookieParser = require('cookie-parser');
var cors=require('cors');
//setup express app
const app = express();
app.use(cors());
//connect to mongodb
mongoose.connect(process.env.MONGODBURI);
mongoose.Promise = global.Promise;
//connect public folder
app.use(express.static('public'));
//bodyparser middleware
app.use(bodyParser.json());
//routes middleware
app.use(cookieParser())
app.use(session({secret: 'MySecret'}));
app.use('/userapi',require('./routes/userapi.js'));
app.use('/cde',require('./routes/cde.js'));
app.use('/efg',require('./routes/efg.js'));
//error handler middleware
app.use(function(err,req,res,next){
res.status(422).send({error: err.message});
});
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log('Express server listening on port', port)
});
package.json
{
"name": "vip",
"version": "0.1.0",
"private": true,
"dependencies": {
"afterglow": "0.0.3",
"afterglowplayer": "^1.1.0",
"axios": "^0.17.1",
"body-parser": "^1.18.2",
"cookie-parser": "^1.4.3",
"cookieparser": "^0.1.0",
"cors": "^2.8.4",
"express": "^4.16.2",
"express-session": "^1.15.6",
"foreman": "^2.0.0",
"fs": "0.0.1-security",
"gifffer": "^1.5.1",
"glamor": "^2.20.40",
"image-map-resizer": "^1.0.3",
"jquery": "^3.3.1",
"marked": "^0.3.12",
"mongoose": "^5.0.1",
"natural": "^0.5.6",
"react": "^16.2.0",
"react-data-menu": "^1.1.1",
"react-dom": "^16.2.0",
"react-gif": "^0.1.0",
"react-modal": "^3.1.13",
"react-scripts": "1.1.0",
"react-toastify": "^3.4.2",
"redux": "^3.7.2",
"shelljs": "^0.8.1",
"video-react": "^0.9.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"devDependencies": {
"nodemon": "^1.14.12",
"react-router-dom": "^4.2.2"
}
}
I've pushed all the code to heroku and I've set the mongodb uri to mlab in heroku dashboard settings. When I request express it gives me a error
GET https://myappname.herokuapp.com/userapi/verifylogin?email=aa&password=aa 404 (Not Found)
createError.js:16 Uncaught (in promise) Error: Request failed with status code 404
at createError (createError.js:16)
at settle (settle.js:18)
at XMLHttpRequest.handleLoad (xhr.js:77)
userapi`
const express = require('express');
const router = express.Router();
const User = require('../models/Login');
const LoginSession = require('../models/LoginSession');
const server = require('../server');
//find a record matching username & Password
router.get('/verifylogin',function(req,res,next){
User.findOne({email:req.query.email,password:req.query.password}).then(function(sequence_data){
res.send(sequence_data);
});
});
module.exports = router;
`
I've gone through many other posts related, but didn't resolved it.

Resources