configure node express to serve static bower_components?

I have a directory structure

projectName
    | - bower_components/
    | - public/
        | - css
        | - js
        | - index.html
    | - Gruntfile.js
    | - package.json
    | - bower.json
    | - app.js

I would like to start my app and serve index.html with node. So in app.js I have:

var express = require('express');
var port = process.env.PORT || 3000;
var app = express();

app.configure(function(){
    // Serve up content from public directory
    app.use(express.static(__dirname + '/public'));
    app.use(app.router);
    app.use(express.logger()); 
});

app.listen(port, function(){
    console.log('Express server listening on port ' + port);
});

At the bottom of index.html I have:

<script src="../bower_components/jquery/jquery.js"></script>
<script src="../bower_components/d3/d3.js"></script>
<script src="../bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="bower_components/spin.js/spin.js"></script>
<script src="bower_components/mustache/mustache.js"></script>

When I start the server, index.html shows up but none of the above libraries load. I get the error (404):

GET http://localhost:3000/bower_components/jquery/jquery.js 404 (Not Found) localhost/:32
GET http://localhost:3000/bower_components/d3/d3.js 404 (Not Found) localhost/:33
GET http://localhost:3000/bower_components/bootstrap/dist/js/bootstrap.js 404 (Not Found) localhost/:34
GET http://localhost:3000/bower_components/spin.js/spin.js 404 (Not Found) localhost/:35
GET http://localhost:3000/bower_components/mustache/mustache.js 404 (Not Found) 

How can I serve the files from bower_components?


Solution 1:

I use this setup:

app.use(express.static(__dirname + '/public'));
app.use('/bower_components',  express.static(__dirname + '/bower_components'));

So any Bower components are loaded from HTML like this:

<script src="/bower_components/..."></script>

And any other client-side JS/CSS (in public/) are loaded like this:

<script src="/js/..."></script>

Solution 2:

You should use

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

Note the usage of (path.join) which is different from @robertklep answer

Here is a note from Another SO questions which according to me captures it very well

path.join will take care of unneccessary delimiters, that may occur if the given pathes come from unknown sources (eg. user input, 3rd party APIs etc.).

So path.join('a/','b') path.join('a/','/b'), path.join('a','b') and path.join('a','/b') will all give a/b.

Without using it, you usually would make expectations about the start and end of the pathes joined, knowing they only have no or one slash.

Solution 3:

Bower can be configured using JSON in a .bowerrc file.

Add an .bowerrc file with the following contents at the root of your project with the contents.

{
  "directory": "public/bower_components"
}

This will place the bower components your are refering to in the correct library and you will not need the extract static directory in express.