Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serve public files from Node app that's deployed to Heroku

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?

like image 887
dchaboya Avatar asked Oct 12 '25 22:10

dchaboya


2 Answers

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.

like image 78
sheldonk Avatar answered Oct 14 '25 12:10

sheldonk


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.

like image 23
Andy Avatar answered Oct 14 '25 14:10

Andy