What is the difference between setting a property on app.locals and calling app.set()?

Problem

I'm in the process of learning Express - and thinking of the best place to save config style data. Options available are either in app.locals or app.set (settings)... so:

app.locals({ config: {
    name: 'My App',
    domain: 'myapp.com',
    viewPath: __dirname+'/views',
    viewEngine: 'jade'
    port: 3000
} });

app.set('view engine', app.locals.config.viewEngine || 'jade');

This would also allow me to use the following in my views:

<title>#{config.name}</title> // <title>My App</title>

Or the alternative is to use app.set like so:

app.set('name', 'My App');
app.set('domain', 'myapp.com');

... and then use this in the view:

<title>#{settings.name}</title>

I know both methods work, but I'm struggling to determine which is the better method to use. At the moment I'm leaning towards using app.locals, with the extra 'app' namespace as I believe there would be less chance of conflicts with future updates and other modules if using app.set.

Problem courtesy of: leepowell

Solution

Wow, all of the answers are wrong, so let me give it a try. Despite what others say assinging to the app.local argument is different from using app.set(). Watch,

app.js
  app.locals.foo = 'bar';
  app.set('baz', 'quz');  


index.jade
  block content                            
    dl                                     
      dt app.locals.foo = 'bar';            
      dd \#{settings.foo} = #{settings.foo}
      dd \#{foo} = #{foo}                  

      dt app.set('baz', 'quz')             
      dd \#{settings.baz} = #{settings.baz}
      dd \#{baz} = #{baz}

If you ran this code, what you would see is,

app.locals.foo = 'bar';
  #{settings.foo} =
  #{foo} = bar
app.set('baz', 'quz')
  #{settings.baz} = quz
  #{baz} =

The reason for this is setting app.locals sets attributes of the object that the view uses as its environment; what the view will read from without qualification. Conversely, app.set sets attributes on app.locals.settings. You can verify this if you clobber app.locals.settings in the above with app.locals.settings = {}, which will make #{settings.baz} undefined.

So which do you use? If it's not an app setting based on the response (res.set) or global configuration (app.set), use the direct write to app.locals.

Solution courtesy of: Evan Carroll

Discussion

Lots of people indeed use locals instead of app.set so my advice is to use that.

Discussion courtesy of: Pickels

The express api reference says :

By default Express exposes only a single app-level local variable, settings.

and either way is ok:

app.locals.title = 'My App';

app.set('title', 'My App');
// use settings.title in a view
Discussion courtesy of: cameron

All properties of app.locals are available in templates. Using app.set assigns properties to app.locals.settings, which is used for global application settings and is inherited by mounted applications. For example:

var app1 = express(),
    app2 = express();

app1.set('inheritable', 'foo');
app1.locals.notInheritable = 'bar';

app1.use('/mount', app2);

app2.get('inheritable') === 'foo'; // true
app2.locals.notInheritable === 'bar'; // false

So it's really a question of preference and whether or not you're mounting applications.

Discussion courtesy of: charliehw

This recipe can be found in it's original form on Stack Over Flow.