4

This has been asked before and I have tried a variety of suggested pathing approaches, but I have yet to figure out how to do it for my case.

I am aware of using ...

1) app.use(express.static(path.join(process.env.PWD, 'public')));
2) app.use(express.static('./public')));
3) app.use(express.static(path.join(__dirname, 'public')));

Locally, options 1 and 2 work but when deployed to Heroku do not work. Options 3 does not work locally.

I think I have figured out why it's not working, which is that the app.use configuration is not used within the js file that starts the server (e.g. server.js). The app.use configuration is located in another file(called express.js) that's in another directory.

This is my setup

asmtax
  --app
    --controllers
    --models
    --routes
    --views
  --config
    --express.js
  --public
    --css
    --js
    --images
  --server.js

Here is my express.js file

process.env.PWD = process.cwd();

var config = require('./config');
var express = require('express');
var morgan = require('morgan');
var compress = require('compression');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
var session = require('express-session');
var flash = require('connect-flash');
var passport = require('passport');
var path = require('path');

module.exports = function() {

//initialize express app
var app = express();

if(process.env.NODE_ENV === 'development') {
  app.use(morgan('dev'));
} else if(process.env.NODE_ENV === 'production') {
  app.use(compress());
}

app.use(bodyParser.urlencoded({extended:true}));

app.use(bodyParser.json());
app.use(methodOverride());

app.use(session({
  saveUninitialized: true,
  resave: true,
  secret: config.sessionSecret
}));

app.set('views', './app/views');
app.set('view engine', 'ejs');

require('../app/routes/index.server.routes.js')(app);
require('../app/routes/about.server.routes.js')(app);

app.use(express.static(path.join(process.env.PWD, 'public')));

return app;

};

This is my server.js file

process.env.NODE_ENV = process.env.NODE_ENV || 'development';
var port = process.env.PORT || 3000;

var express = require('./config/express');

var app = express();

app.listen(port, function () {
  console.log('listening on port ' + port);
  console.log(require('fs').existsSync(__dirname + '/public'));
});

module.exports = app;

Any suggestions on how to get this to work?

dchaboya
  • 175
  • 2
  • 8

3 Answers3

2

Try

app.use(express.static(path.join(__dirname, '../public')));

__dirname refers to the directory of the file. Since 'express.js' is in the config directory. You need to go up one level to access public.

sheldonk
  • 2,604
  • 3
  • 22
  • 32
  • You probably want to do the same thing "path.join(__dirname, '../app/views');" with your views path. – sheldonk Jan 29 '15 at 23:10
  • Ok, this is now working locally, but still not on heroku. Still getting 404's for all the public files. – dchaboya Jan 30 '15 at 13:09
  • Looks like you can't use _dirname when deploying to [heroku](http://stackoverflow.com/questions/17212624/deploy-nodejs-on-heroku-fails-serving-static-files-located-in-subfolders?rq=1). Looks like you are suppose to use process.env.PWD. When I use app.use(express.static(path.join(process.env.PWD, 'public'))) it works locally and when I console.log that path it returns the right pathing. However, this still does not work on heroku. – dchaboya Jan 30 '15 at 14:33
  • The answer to that suggests that you add the npm version to your package.json. This issue suggests that you can use __dirname. https://github.com/autoric/express-train/issues/23 __dirname is drastically different than process.env.PWD – sheldonk Jan 30 '15 at 21:03
2

I'm not sure that it matters, but the answer from @sheldonk has a / buried in his usage of path.join still. I went with something slightly different that works well, but it was built on top of his answer, so I gave his answer a plus 1 for the inspiration.

app.use(express.static(path.join(__dirname, '..', 'public')));

path.join supports N arguments and combines them all together appropriately.

Andy
  • 648
  • 8
  • 21
0

For me, __dirname does work. My JS-containing folder happened to be capitalized in my layout file, but wasn't in the folder structure.

So, like /public/Bootstrap/js was causing probs. Renamed it to /public/bootstrap/js, and that works just fine, even with __dirname.

Qasim
  • 1,554
  • 1
  • 13
  • 22