I know there are other answers to this but they seem to have caveats.
This one causes a redirect, which can be fatal for my front-end app which uses Mixpanel, and a double-load of Mixpanel will a Maximum Call Stack Size Exceeded error in the browser.
This one uses sendFile
which I personally cannot get to work. Trying to diagnose that, I'm just advised to use express.static()
.
Currently my code looks like this:
home.js - Some routes, the last one intended to be the front-end site.
var indexPath = path.resolve( __dirname, '../' + process.env.PUBLIC_FOLDER )
router.get( '/:user/:stream/:slug', function( req, res, next ) {
if ( req.headers['user-agent'].indexOf( 'facebook' ) != -1 ) {
// stuff to handle the Facebook crawler
} else return next()
})
router.get( '/*', function( req, res ) {
express.static( indexPath )
})
server.js - configuring node/express
app = express();
app
.use( morgan( 'dev' ) )
.use(bodyParser.urlencoded( { limit: '50mb', extended: true } ) )
.use( bodyParser.json( { limit: '50mb' } ) )
.use( '/api', require('./routes/usersRoute.js') )
.use( '/', require( './routes/home' ) )
.on( 'error', function( error ){
console.log( "Error: " + hostNames[i] + "\n" + error.message )
console.log( error.stack )
})
http
.createServer( app ).listen( process.env.PORT )
.on( 'error', function( error ){
console.log( "Error: " + hostNames[i] + "\n" + error.message )
console.log( error.stack )
})
Some more info
The reason you can see I'm trying to use express.static()
is because when I use res.sendfile()
I get a problem like this one where the console says Unexpected token '<'
. Unfortunately the answer doesn't specify an exact fix and neither does the questioner who says they fixed the problem but don't share an answer.
In my trial and error I have added some more to express, like this
.use( '/app/app.js', express.static( indexPath + '/app/app.js' ) )
.use( '/app/views', express.static( indexPath + '/app/views' ) )
.use( '/app/controllers', express.static( indexPath + '/app/views' ) )
.use( '/app/directives', express.static( indexPath + '/app/views' ) )
.use( '/app/vendor', express.static( indexPath + '/app/vendor' ) )
.use( '/js', express.static( indexPath + '/js' ) )
.use( '/css', express.static( indexPath + '/css' ) )
.use( '/fonts', express.static( indexPath + '/fonts' ) )
.use( '/images', express.static( indexPath + '/images' ) )
.use( '/api', require('./routes/usersRoute.js') )
.all( '/*', require( './routes/home' ) )
And in my home.js
routes files added this
router.get( '/*', function ( req, res ) {
res.status( 200 ).set( { 'content-type': 'text/html; charset=utf-8' } )
.sendfile( indexPath + '/index.html' )
})
And in the browser I can see all my files are loading, but with the <
error above. I see this /*/
route is being called hundreds of times when I do a refresh so I think the .use( '...', ... )
configurations are being ignored.
Here is another example requested by Jonas below.
var indexPath = path.resolve( __dirname, process.env.PUBLIC_FOLDER )
mongoose.connect( process.env.MONGOLAB_URI )
app = express();
app
.use( morgan( 'dev' ) )
.use(bodyParser.urlencoded( { limit: '50mb', extended: true } ) )
.use( bodyParser.json( { limit: '50mb' } ) )
.use( '/api', require('./routes/usersRoute.js') )
.use( '/', require( './routes/home.js' ) )
.use( express.static( indexPath ) )
.on( 'error', function( error ){
console.log( "Error: " + hostNames[i] + "\n" + error.message )
console.log( error.stack )
})
I have also done the same without the .use( '/', require( './routes/home.js' ) )
line to try narrow down any problem, but it's the same result. The page will load if I have the #
in the URL, but the browser will remove the #
(so far so good). But if I press refresh, or put in the URL manually, sans-hashbang, it will give an error like Cannot GET /home/splash
, where /home/splash
is whatever path I'm going to.
Yes. Node. js required for Angular 2 or Angular apps.
Is putting angular in the dist folder what makes it run in the same port with express? Yes.
Advertisements. Routing basically means navigating between pages. You have seen many sites with links that direct you to a new page. This can be achieved using routing.
You might be using the express middleware in the wrong way. Looking at the documentation tells me for example that the following code
.use( '/images', express.static( indexPath + '/images' ) )
Serves any file under the folder indexPath + '/images'
with such URLs:
http://localhost:3000/images/kitten.jpg
http://localhost:3000/images/logo.png
http://localhost:3000/images/whatever.jpg
Is that what you would expect it to do?
My suggestion is to change from
.use( '/', require( './routes/home' ) )
to
.use(express.static( indexPath ))
Because according to the documentation, it will serve all static files under the indexPath
folder from the root path, aka. with no prefix.
I think that is all I can help with the input you gave so far. If that doesn't do the trick, maybe you can share some small code example that I can use to reproduce it on my own.
Ok. I've tried to create a simple example of it. I made it work in the following way. My directory structure is like this:
|- index.js
|- public/
|---- index.html
|---- test.html
|---- main.js
|---- angular.js
|---- angular-route.js
index.js
is the node server. Pay attention to the order of the routing. I also added some /home/login
example to make it clear how to add other server routes that should not go through angular.
var http = require('http');
var express = require('express');
var app = express();
app
.use(express.static('public'))
.get('/home/login', function (req, res) {
console.log('Login request');
res.status(200).send('Login from server.');
})
.all('/*', function ( req, res ) {
console.log('All');
res
.status( 200 )
.set( { 'content-type': 'text/html; charset=utf-8' } )
.sendfile('public/index.html' );
})
.on( 'error', function( error ){
console.log( "Error: \n" + error.message );
console.log( error.stack );
});
http
.createServer( app ).listen( 8080 )
.on( 'error', function( error ){
console.log( "Error: \n" + error.message );
console.log( error.stack );
});
console.log('Serving app on port 8080');
index.html
is pretty simple.
<!doctype html>
<html>
<head>
<title>Angular HTML5 express test</title>
<script type="text/javascript" src="angular.js"></script>
<script type="text/javascript" src="angular-route.js"></script>
<script type="text/javascript" src="main.js">
</script>
</head>
<body ng-app="app">
<div ng-view></div>
</body>
</html>
main.html
just adds some content. Important is the link to /test
<div>
<h1>This is just a {{val}}</h1>
<button ng-click="clicked()">Click me!</button>
<span>You clicked {{counter}} times</span>
<a href="/test">test me!</a>
</div>
test.html
is actually irrelevant
<div>
<h4>What a beautiful day to test HTML5</h4>
</div>
main.js
is doing the core angular html5 work
angular.module('app', ['ngRoute'])
.config(function($locationProvider) {
$locationProvider
.html5Mode({
enabled: true, // set HTML5 mode
requireBase: false // I removed this to keep it simple, but you can set your own base url
});
})
.config(function($routeProvider) {
$routeProvider
.when('/test', {templateUrl: 'test.html', controller: function() {
console.log('On /test.');
}})
.when('/', {templateUrl: 'main.html', controller: 'MyTestCtrl'})
.otherwise('/');
})
.controller('MyTestCtrl', function ($scope) {
self = $scope;
self.val = 'TeSt';
self.counter = 0;
var self = self;
self.clicked = function() {
self.counter++;
};
});
instead of:
router.get( '/*', function( req, res ) {
express.static( indexPath )
})
do
router.get( '/:anyreq', function( req, res ) {
express.static( indexPath )
})
just keep it at end of routes file.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With