Webpack not detecing proxy for local development - node.js

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)
}

Related

PERN stack app on Heroku syntax error: Unexpected token < in JSON at position 0

I am trying to deploy my first React.js app on Heroku. Everything seems to work fine link to app except the most important part - the Express.js REST API that I use to fetch data from my Postgres database and Stripe API is functioning normally on localhost, but when I deploy the app on Heroku, all the API routes I am trying to access return the same syntax error - Unexpected token < in JSON at position 0.
I understand that the issue is tied to how my app routes to the API. In other words, the fetch request is not able to get to the needed endpoint and thus return this syntax error, but I can't pinpoint exactly where is the issue - am I missing a '/' somewhere, have I incorrectly set up my environment variables, etc.?
Has someone had a similar issue or maybe someone can spot the issue in my code down below?
package.json
{
...
"private": true,
"main": "server.js",
"homepage": "https://dj-bbq.herokuapp.com",
"engines": {
"npm": "6.14.15",
"node": "14.18.1"
},
"dependencies": {
"#formspree/react": "^2.2.4",
"#stripe/react-stripe-js": "^1.7.0",
"#stripe/stripe-js": "^1.22.0",
"#testing-library/jest-dom": "^5.16.1",
"#testing-library/react": "^12.1.2",
"#testing-library/user-event": "^13.5.0",
"#userfront/react": "^0.2.22",
"cors": "^2.8.5",
"express": "^4.17.2",
"express-fileupload": "^1.2.1",
"helmet": "^5.0.1",
"jsonwebtoken": "^8.5.1",
"pg": "^8.7.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^6.2.1",
"react-scripts": "4.0.3",
"stripe": "^8.195.0",
"web-vitals": "^2.1.2"
},
"devDependencies": {
"dotenv": "^10.0.0",
"nodemon": "^2.0.15",
"source-map-explorer": "^2.5.2"
},
"scripts": {
"start": "node server.js",
"heroku-postbuild": "npm install && npm run build",
"dev-start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"analyze": "source-map-explorer 'build/static/js/*.js'",
"server": "node server.js",
"nodemon": "nodemon server.js"
},...
server.js
const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const path = require('path'); // Allows to access files through the server in our filesystem
const fileUpload = require('express-fileupload'); // Parses multipart/form-data requests, extracts the files if available, and make them available under req.files property.
/**
** ------------- GENERAL SETUP -------------
*/
// Provides access to variables from the .env file by using process.env.REACT_APP_variable_name
require('dotenv').config();
const nodeEnv = process.env.NODE_ENV !== 'production';
const devPort = process.env.REACT_APP_server_dev_port;
const prodPort = process.env.PORT // process.env.PORT
const devDomain = process.env.REACT_APP_dev_domain;
const prodDomain= process.env.REACT_APP_prod_domain;
const PORT = nodeEnv ? devPort : prodPort;
const domain = nodeEnv ? devDomain : prodDomain;
// CORS options
const corsOptions = {
origin: domain, // frontend_URL for heroku deployment
credentials: true ,
// Allows only the following HTTP requests to go through
methods: [
"PUT",
"POST",
"DELETE",
"GET",
],
"Access-Control-Allow-Headers": [
"Origin",
"X-Requested-With",
"Content-Type",
"Accept",
"Authorization",
],
};
//* Creates the Express server instance as "app"
const app = express();
//* MIDDLEWARE
// Called BETWEEN processing the Request and sending the Response in your application method.
app.use(helmet()); // Sets many http headers to make them more secure
app.use(cors(corsOptions)); // To allow cross origin conections (Allows our React app to make HTTP requests to Express application)
// Instead of using body-parser middleware, use the new Express implementation of the same thing
app.use(express.json()); // To recognize the incoming Request Object (req.body) as a JSON Object
app.use(express.urlencoded({ extended: true })); // To recognize the incoming Request Object as strings or arrays
app.use(fileUpload({
createParentPath: true
})); // Enables file uploading
//* HEROKU MIDDLEWARE
if (process.env.NODE_ENV !== 'production') {
// To load static files or client files from here http://localhost:3000/images/kitten.jpg
app.use(express.static(path.join(__dirname, 'public')));
} else if (process.env.NODE_ENV === 'production') {
// Serve static files - makes the build folder accessible to app.
app.use(express.static(path.joins(__dirname, 'build')));
// app.use(express.static(path.resolve(__dirname, 'build')));
}
/**
** -------------- SERVER ----------------
*/
// Determines the PORT and enables LISTENing for requests on the PORT (http://localhost:8000)
app.listen(PORT, () => {
console.debug(`Server is listening at http://localhost:${PORT}`);
});
/**
** ------- ROUTES / ENDPOINTS ---------
*/
// Go to /test to make sure the basic API functioning is working properly
app.get('/test', (req, res) => {
res.status(200).send('The Basic API endpoints are working.')
});
// Imports all of the routes from ./routes/index.js
app.use(require('./app-server/routes/allRoutes'));
// If req comes from one of these domains (origins), then allow the request with CORS.
app.use((req, res, next) => {
const corsWhitelist = [
domain,
];
if (corsWhitelist.indexOf(req.headers.origin) !== -1) {
res.header('Access-Control-Allow-Origin', req.headers.origin);
}
next();
});
I have set-up a catch all route (router) for unkown routes in a different file
//* HEROKU - catch all for unrecognised routes
if (process.env.NODE_ENV === 'production') {
// Serve index.html file if it doesn't recognize the route
router.get('*', (req, res, next) => { // or * instead of /
res.sendFile(path.join(__dirname, 'build', 'index.html')); // resolve instead of join
})
}
And here is an example of a fetch request
const [recipes, setRecipes] = useState([]);
useEffect(() => {
let interval;
const fetchData = async () => {
try {
// const url = 'http://localhost:8000/recipes/display';
const url = `${customProxy}/recipes/display`;
const response = await fetch(url);
const json = await response.json();
setRecipes(json);
} catch(error) {
// console.error(error);
alert("Recipe displaying:" + error);
}
};
fetchData();
interval = setInterval(() => {
fetchData()
}, 86 * 1000)
return () => {
clearInterval(interval)
}
}, []); // Determine swhen to re-use useEffect, if this changes.
Thank you in advance for taking the time to consider the solution for issue!
Update 1
I started going through my project for the n-th time and previously I followed the guides found on Heroku to deploy my PERN app. The guides recommended using mars/create-react-app-buildpack to deploy the app, but after reading the documentation of this build pack it clearly says that this build pack is only meant for static react apps not react apps with its own custom node.js server.
In such cases, I am to use the mars/heroku-cra-node.
I have been following the documentation on how to set-up my folder structure, etc., but now, when I deploy the app, Heroku informs me of the following...
-----> Building on the Heroku-20 stack
-----> Using buildpacks:
1. https://github.com/mars/heroku-cra-node
-----> App not compatible with buildpack: https://github.com/mars/heroku-cra-node
bash: /tmp/codon/tmp/buildpacks/d07ae047a3685d9cfb39224105301a7dbdbfbe9c/bin/detect: No such file or directory
More info: https://devcenter.heroku.com/articles/buildpacks#detection-failure
! Push failed
I understand that the idea is that my folder structure is not as required by the build pack, but I am following its documentation by the letter.
Has anyone had any experience in using this build pack to deploy a PERN app to Heroku?
I noticed that this question of mine is still unanswered.
The issue, in the end, was that I was trying to use the Heroku free plan, but my app was too "big" for that so I either needed to split the back-end and front-end into two apps or to use a paid plan.
In the end, I actually changed my hosting service provider from Heroku to Digital Ocean. The app is still on their servers and works now - https://dj-bbq-i5gdc.ondigitalocean.app/ .

Node.JS integration test error: listen EADDRINUSE: address already in use :::3000

I've used jest and supertest for integration tests. In afterEach section I closed server:
let server;
describe('/api/user', () => {
beforeEach(() => {
server = require('../../../app');
});
afterEach(async () => {
await server.close();
});
//some tests
});
But by running npm test I get this error:
listen EADDRINUSE: address already in use :::3200
When I using just one something.test.js file, everything is OK. The problem is when I add a new something.test.js. What's wrong?
Here is the package.json:
{
"name": "users",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "jest --watchAll"
},
"author": "Saeed Heidarbozorg",
"license": "ISC",
"dependencies": {
"config": "^3.3.4",
"express": "^4.17.1",
"express-async-errors": "^3.1.1",
"joi": "^17.4.0",
"morgan": "^1.10.0",
"pg": "^8.5.1",
"winston": "^3.3.3"
},
"devDependencies": {
"jest": "^26.6.3",
"supertest": "^6.1.3"
}
}
tl;dr in a test environment, you don't want to create an http server at all, just test your express app instance.
If you want to post your code from your app.js, I can probably give you a quicker fix.
In general this is the way I structure it to facilitate accomplishing the tl;dr:
app.js contains all the express-y stuff:
import express from 'express';
const app = express();
// ... do all your express-y stuff
export default app;
index.jsis the entry point to the app that starts the server. This file IS NOT NEEDED during testing:
import http from 'http';
import app from './app';
http.createServer(app).listen(...);
When testing, you don't need index.js at all, just import your express app from app.js and test it:
Some test file:
import app from './app';
import request from 'supertest';
describe('...',() => {
test('...', async () => {
expect((await request(app).get('/some/route')).status).toBe(200);
});
});

laravel vuejs socket.io Access-Control-Allow-Origin

hello laravel i am trying to use socket.io with vuejs but i keep getting errors, i couldn't understand where i went wrong.
What I want to do is clearly when the form is submitted, it is listened to by the audience and instantly sees the post to the manager. Of course, this is not happening. I am using socket.io wrong. I couldn't understand.
laravel.local/:1 Access to XMLHttpRequest at 'http://localhost:3000/socket.io/?EIO=3&transport=polling&t=NNy_ruN' from origin 'http://laravel.local:8000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
server.js
var app = require('express')();
const server = require('http').createServer();
const io = require('socket.io')(server);
// http.listen(3000);
app.get('/', (req, res) => {
res.send('<h1>Hello world</h1>');
});
io.on('connection', socket => {
socket.on('new_appointment_create', function () {
console.log("okey");
io.emit('admin_appointment_list');
});
});
server.listen(3000, function () {
console.log('Listening on Port: 3000');
});
formpost.vue
import io from 'socket.io-client';
var socket = io('http://localhost:3000');
.then((response) => {
if (response.status) {
socket.emit('new_appointment_create');
this.completeForm = false;
}
})
adminlist.vue
import io from 'socket.io-client';
var socket = io('http://localh
created() {
this.getData();
socket.on('admin_appointment_list', () => {
console.log("list okey");
this.getData();
});
},
package.json
"devDependencies": {
"axios": "^0.19",
"bootstrap": "^4.0.0",
"cross-env": "^7.0",
"jquery": "^3.2",
"laravel-mix": "^5.0.1",
"lodash": "^4.17.19",
"popper.js": "^1.12",
"resolve-url-loader": "^3.1.2",
"sass": "^1.20.1",
"sass-loader": "^8.0.0",
"socket.io": "^3.0.3",
"socket.io-client": "^2.3.1",
"vue": "^2.5.17",
"vue-template-compiler": "^2.6.10"
},
"dependencies": {
"express": "^4.17.1",
"laravel-vue-pagination": "^2.3.1",
"v-mask": "^2.2.3",
"vue-resource": "^1.5.1"
}
The error you're receiving is due a feature from browsers called preflight that consists in the browser doing kind of "ping request" to the server that you want to access with an HTTP OPTIONS to get the response headers and check for the Access-Control-Allow-Origin header.
The idea is that your API should declare in this header which origins(domains) are allowed to consume your resources/APIs.
The "easiest" way to resolve this is to configure your API to respond with Access-Control-Allow-Origin: *.
But it's not the correct way, you shouldn't go to production * as configuration.
In my opinion the correct way to resolve this is use a http proxy while in dev, and in production you configure your Apache or NGINX or whatever http server you'll use to do so.
If you're using #vue/cli, it already has an option to configure a proxy server for development, take a look in the docs.
But fastforwarding the refactoring needed if you use the devProxy option, you will basically map an resource/context in the same server/port which is served you front-end to proxy requests/connections to your websocket.
Then you'll stop calling the http://localhost:3000 directly and will use the mapped resource/context.
For example:
In your vue.config.js
module.exports = {
devServer: {
proxy: {
'^/api': {
target: 'http://localhost:300',
ws: true
}
}
}
}
Then you will create the socket:
var socket = io(`${location.protocol}//${location.host}/api`);
Being honest with you, I've never used the devProxy with websockets, but the docs says it has support for it.

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

Issue running Next.js on iisnode on Azure Web App

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"
}

Resources