I was having the exact same problem you were having, and have 2 possible solutions for you!
//////////////////////////////
Solution #1: List the directories you do/don't want "served"
//////////////////////////////
How to:
Let's say your directory structure is like this:
-app/
---controllers/
---directives/
---etc.
-public/
---img/
---css/
---index.html
---etc.
-views/
---home.html
---vehicle.html
---etc.
-app.js (run with 'node app.js')
Some of these 3 folders (app,public,views) have different rules on which you want to serve and which you want to render:
- app/
- serve: If your site does GET /app/controller.js, you want to serve them the literal file.
- public/
- serve: If your site does GET /public/img/logo.jpg, you want to serve them the literal file.
- views/
- render: If your site does GET views/home, you want to render them the view from your angular.js route.
Now from your node/express js file, locate or add the following:
//This tells node that these folders are for STATIC SERVING files (meaning literal files).
//And Yes! You can use multiple to indicate multiple directories.
app.use(express.static(path.join(__dirname, 'app')));
app.use(express.static(path.join(__dirname, 'public')));
More Info:
app.use(express.static(__dirname + '/client/views')); means you are serving literal files from /client/views but nothing OUTSIDE of that directory. See angularjs index.html in views folder
Expanded Example:
This would be your possible configuration:
//app.js
var express = require('express'),
bodyParser = require('body-parser'),
methodOverride = require('method-override'),
errorHandler = require('error-handler'),
morgan = require('morgan'),
routes = require('./routes/index'), //My special routes file
http = require('http'),
path = require('path');
var app = module.exports = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(morgan('dev'));
app.use(bodyParser());
app.use(methodOverride());
app.use(express.static(path.join(__dirname, 'app')));
app.use(express.static(path.join(__dirname, 'public')));
// serve index and view partials
app.get('/', routes.index);
//Partials
app.get('/partials/:name', routes.partials);
// redirect all others to the index
// BUT the static files listed above still get served statically
app.get('*', routes.index);
http.createServer(app).listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
Then this would be your routes file:
exports.index = function(req, res){
res.render('index');
};
exports.partials = function (req, res) {
var name = req.params.name;
res.render('partials/' + name);
};
//////////////////////////////
Solution #2: Check if the file exists first
//////////////////////////////
How to:
Keep everything how you already have it, but instead of trying "res.sendFile" immediately, check if it exists first. For example:
exports.all = function (req, res) {
var name = req.params[0];
fs.exists(path+'/'+name, function(exists){
if(exists)
{
//console.log("file exists");
res.sendFile(path+'/'+name);
}else{
//console.log("file does not exist");
//redirects to index
res.render('index');
}
});
};
Expanded Example:
This would be your possible configuration:
//app.js
var express = require('express'),
bodyParser = require('body-parser'),
methodOverride = require('method-override'),
errorHandler = require('error-handler'),
morgan = require('morgan'),
routes = require('./routes/index'), //My special routes file
http = require('http'),
path = require('path');
var app = module.exports = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(morgan('dev'));
app.use(bodyParser());
app.use(methodOverride());
app.use(express.static(path.join(__dirname, '')));
// serve index and view partials
app.get('/', routes.index);
//Partials
app.get('/partials/:name', routes.partials);
// redirect all others
app.get('*', routes.all);
http.createServer(app).listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
and this is your routes file:
var fs = require('fs');
var path = require('path');
exports.index = function(req, res){
res.render('index');
};
exports.partials = function (req, res) {
var name = req.params.name;
res.render('partials/' + name);
};
exports.all = function (req, res) {
var name = req.params[0];
fs.exists(path+'/'+name, function(exists){
if(exists)
{
//console.log("file exists");
res.sendFile(path+'/'+name);
}else{
//console.log("file does not exist");
//redirects to index
res.render('index');
}
});
};
//////////////////////////////
Hope that helps!