How to fix the "SyntaxError: Unexpected token < in JSON at position 0" error after deploying to the azure portal

I used express node.js and angular to build a web application which need to read the date from the mongodb database. I ran "ng build --prod" to put all the files in the dist folder, and I copied it to the node.js project folder.

The project structure is

  • /dist (including web.config)
  • /server/routes/api
  • /node_modules
  • server.js
  • package.json
  • package-lock.json

When I deployed my application to the azure portal via GitHub, the following error is showed:

core.js:1448 ERROR SyntaxError: Unexpected token < in JSON at position 0
    at JSON.parse (<anonymous>)
    at Response.webpackJsonp../node_modules/@angular/http/esm5/http.js.Body.json (http.js:1091)
    at MapSubscriber.project (data.service.ts:15)
    at MapSubscriber.webpackJsonp../node_modules/rxjs/_esm5/operators/map.js.MapSubscriber._next (map.js:79)
    at MapSubscriber.webpackJsonp../node_modules/rxjs/_esm5/Subscriber.js.Subscriber.next (Subscriber.js:92)
    at XMLHttpRequest.onLoad (http.js:1591)
    at ZoneDelegate.webpackJsonp../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
    at Object.onInvokeTask (core.js:4740)
    at ZoneDelegate.webpackJsonp../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
    at Zone.webpackJsonp../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)

The Application Setting of the azure portal is here:

Setting 1

Setting 2

server.js:

const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const http = require('http');
const app = express();

// API file for interacting with MongoDB
const api = require('./server/routes/api');

// Parsers
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false}));

// Angular DIST output folder
app.use(express.static(path.join(__dirname, './dist')));

// API location
app.use('/api', api);

// Send all other requests to the Angular app
app.get('/*', (req, res) => {
    res.sendFile(path.join(__dirname, './dist/index.html'));
});

//Set Port
const port = process.env.PORT || '1337';
app.set('port', port);

const server = http.createServer(app);

server.listen(port, () => console.log(`Running on localhost:${port}`));

module.exports = app;

api.js:

const express = require('express');
const router = express.Router();
const MongoClient = require('mongodb').MongoClient;
const ObjectID = require('mongodb').ObjectID;

// Connect
const connection = (closure) => {
    return MongoClient.connect('<myURL>', (err, db) => {
        if (err) return console.log(err);

        closure(db);
    });
};

// Error handling
const sendError = (err, res) => {
    response.status = 501;
    response.message = typeof err == 'object' ? err.message : err;
    res.status(501).json(response);
};

// Response handling
let response = {
    status: 200,
    data: [],
    message: null
};

// Get users
router.get('/users', (req, res) => {
    connection((db) => {
        db.collection('botdata')
            .find()
            .toArray()
            .then((users) => {
                response.data = users;
                res.json(response);
            })
            .catch((err) => {
                sendError(err, res);
            });
    });
});

module.exports = router; 

data.service.ts

import { Injectable } from '@angular/core';

import { Http, Headers, RequestOptions } from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class DataService {

  result:Array<any>;

  constructor(private _http: Http) { }

  getUsers() {
    return this._http.get("/api/users")
      .map(result => this.result = result.json().data);
  }
}

app.component.ts

import { Component } from '@angular/core';

// Import the DataService
import { DataService } from './data.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  // Define a users property to hold our user data
  users: Array<any>;

  // Create an instance of the DataService through dependency injection
  constructor(private _dataService: DataService) {

    // Access the Data Service's getUsers() method we defined
    this._dataService.getUsers()
        .subscribe(res => this.users = res);
  }
}

web.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <!-- Indicates that the app.js file is a node.js site to be handled by the iisnode module -->
      <add name="iisnode" path="./server.js" verb="*" modules="iisnode"/>
    </handlers>
    <rewrite>
      <rules>
        <rule name="AngularJS" stopProcessing="true">
          <match url="^(?!.*(.bundle.js|.bundle.map|.bundle.js.gz|.bundle.css|.bundle.css.gz|.png|.jpg|.ico|.svg|.eot|.woff|\​.woff2)).*$" />
          <conditions logicalGrouping="MatchAll"></conditions>
          <action type="Rewrite" url="/" appendQueryString="true" />
        </rule>

        <rule name="Express.js URIs">
          <match url="api/*" />
          <action type="Rewrite" url="../server.js" />
        </rule>


      </rules>
    </rewrite>
    <staticContent>
      <remove fileExtension=".svg" />
      <remove fileExtension=".eot" />
      <remove fileExtension=".woff" />
      <remove fileExtension=".woff2" />
      <mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
      <mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" />
      <mimeMap fileExtension=".woff" mimeType="application/font-woff" />
      <mimeMap fileExtension=".woff2" mimeType="application/font-woff" />
    </staticContent>
  </system.webServer>
</configuration>

And from the console, the code .map(result => this.result = result.json().data);

may cause this problem but I am not sure this. Any help from you will be appreciated.