简体   繁体   中英

Rewrite requests from loopback to angular2 (Refused to execute script because its MIME type ('text/html') is not executable)

I am using loopback as a backend api and angular2 as a frontend.

I am using loopback to also serve my angular2 frontend.

This works fine, however, once I refresh a page, loopback does not know how to handle the url because this is angular's job, not loopback.

So I get this error :

在此处输入图片说明

I understand 100% why I get this error, because once loopback loads my index.html, then angular2 is bootstrapped and knows how to handle those type of URLs because this is specified in my app.routing.ts file. However, when this link is directly accessed, angular2 is not bootstrapped and loopback does not know how to handle this type of URL.

So I have added code in my loopback code in server.js to redirect all requests to angular except /api that I use for loopback.

Here is the code :

var path = require('path');

var ignoredPaths = ['/api'];

app.all('/*', function(req, res, next) {
  //Redirecting to index only the requests that do not start with ignored paths
  if(!startsWith(req.url, ignoredPaths))
    res.sendFile('index.html', { root: path.resolve(__dirname, '..', 'client') });
  else
    next();
});

function startsWith(string, array) {
  for(let i = 0; i < array.length; i++)
    if(string.startsWith(array[i]))
      return true;
  return false;
}

This works, however, the index.html page is not loaded and I get the following console errors :

Refused to execute script from 

'http://localhost:3000/inline.bundle.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
59074ce…:1 Refused to execute script from 'http://localhost:3000/polyfills.bundle.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
59074ce…:1 Refused to execute script from 'http://localhost:3000/scripts.bundle.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
59074ce…:1 Refused to execute script from 'http://localhost:3000/styles.bundle.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
59074ce…:1 Refused to execute script from 'http://localhost:3000/vendor.bundle.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
59074ce…:1 Refused to execute script from 'http://localhost:3000/main.bundle.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.

I understand the error, but dont know why i am receiving this and dont know how to fix this.

This is my middleware.json file for my loopback backend:

{
  "initial:before": {
    "loopback#favicon": {}
  },
  "initial": {
    "compression": {},
    "cors": {
      "params": {
        "origin": true,
        "credentials": true,
        "maxAge": 86400
      }
    },
    "helmet#xssFilter": {},
    "helmet#frameguard": {
      "params": [
        "deny"
      ]
    },
    "helmet#hsts": {
      "params": {
        "maxAge": 0,
        "includeSubdomains": true
      }
    },
    "helmet#hidePoweredBy": {},
    "helmet#ieNoOpen": {},
    "helmet#noSniff": {},
    "helmet#noCache": {
      "enabled": false
    }
  },
  "session": {},
  "auth": {},
  "parse": {
    "body-parser#json": {},
    "body-parser#urlencoded": {"params": { "extended": true }}
  },
  "routes": {
    "loopback#rest": {
      "paths": [
        "${restApiRoot}"
      ]
    }
  },
  "files": {
    "loopback#static": {
      "params": "$!../client/"
    }
  },
  "final": {
    "loopback#urlNotFound": {}
  },
  "final:after": {
    "strong-error-handler": {}
  }
}

According to angular.io docs , "Routed apps must fallback to index.html" . This means that if loopback cannot "GET" or result in any type of 404, it means that loopback does not understand the url and it needs to "fallback" to the index.html of the angular2 or angular4 app.

To fix this, you will have to add custom middleware to redirect loopback to your angular index so that angular's router can take it from there.

So in your middleware.json file, change the following :

"final": {
    "./middleware/custom404": {}
    }

Then add a file custom404.js inside /server/middleware/ so that the full path is /server/middleware/custom404.js . If the middleware directory does not exist, create it.

Then inside the custom404.js file :

'use strict';
module.exports = function () {
    var path = require('path');
    return function urlNotFound(req, res, next) {
        let angular_index = path.resolve('client/index.html');
        res.sendFile(angular_index, function (err) {
            if (err) {
                console.error(err);
                res.status(err.status).end();
            }
        });
    };
};

This will redirect back to your angular app and angular's router will route the url correctly while still being served by loopback.

Important

It is therefore no longer needed to redirect the app via server.js as I tried to do in the opening question above !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM