14

While working on an express project, I am trying to use an express.Router object to handle my application routes. In my main app file, I have added a static route for all my static files(css, javascript, html).

app.js

var express = require('express');
var io = require('socket.io')(app);
var bodyParser = require('body-parser');
var router = require('./include/router');

var app = express();
app.use('/', router);
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.json());

io.on('connection', function(socket) {

});

app.listen(3000);

router.js

var express = require('express');
var path = require('path');

var router = express.Router();

router.get('/', function(req, res) {
  res.sendFile('/html/index.html');
});

module.exports = router;

When I try to access localhost:3000 I get a 404 showing Error: ENOENT, stat 'C:\html\index.html'

Furthermore, when I try to access the static route directly(http://localhost:300/html/index.html I believe), but that gives me Cannot GET /html/index.html.

This is the tree of my public folder

public
├───css
├───hmtl
|   └───index.html
├───img
└───js

Am I routing this wrong? How can I fix it?

James Parsons
  • 6,097
  • 12
  • 68
  • 108
  • `app.use` will invoke middleware for all requests that match the path argument in the order they are supplied. I recommend doing config and statics before routes. That should fix the issue. – undefined Jan 26 '15 at 01:04
  • I have tried switching the router and static lines, but it did not work, Is there any chance I could create a static route from the `express.Router` object? – James Parsons Jan 26 '15 at 01:17
  • You potentially have two problems. `res.sendFile('/html/index.html');` doesn't make sense, because that is an absolute path, you probably mean `res.sendFile(__dirname + '../public/html/index.html');`. As for `http://localhost:300/html/index.html`, your file tree example has `hmtl`, is that actually a typo on your machine, or just the example? – loganfsmyth Jan 26 '15 at 01:25
  • You could also try supplying a path for statics like `app.use('/public', express.static(__dirnam + '/public'))`, that might clear up any route confictions if thats the case – undefined Jan 26 '15 at 01:27
  • I have fixed the `hmtl` typo, and tried the other path but now ot comes up with`Error: ENOENT, stat 'C:\Users\James\Desktop\template\include..\public\html\index.html'` I also added the path of the statics. None of it is working :( – James Parsons Jan 26 '15 at 01:33
  • @James_Parsons Sorry, typo in my example as that path makes pretty clear, it should be `'/../public/html/index.html'`, not `'../public/html/index.html'`. Is `http://localhost:300/html/index.html` working with the `hmtl` typo fixed? – loganfsmyth Jan 26 '15 at 02:14

1 Answers1

22

You must inverse the order of your router

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

means your router will be called first and, if no middleware handles the request, then express will call static files so, if you put the static middleware first, the express will handle static files first.

It is also recommended to put static middleware first.

For your problem you should try this:

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

Express will try static files first on public/html folder, then on the rest (including the public/html), i prefer putting html files on the root of public folder or maybe on a different folder (e.g public-html, static-html)

Sergio Marcelino
  • 1,142
  • 8
  • 17
  • 2
    For some reason when using parameters in the router with `mergeParams:true` option, this seems not to work and the router will try to serve static files under current route like `/myuri/js/main.js` as described here: http://stackoverflow.com/questions/15128849/using-multiple-parameters-in-url-in-express – loretoparisi Feb 22 '17 at 09:08
  • 2
    @loretoparisi This is exactly my problem and I can't find any solution to it. My routes that have parameters don't load in the css and js sources like my other routes. It tries to load in a directory of the non-parameterized part of the route. Like if route is '/newItem:id' it looks for a folder called newItem. Why is it doing this?? – Matthew Wolman May 21 '20 at 20:35
  • I think I have solved it in some way time ago. I will post a solution here. – loretoparisi May 21 '20 at 21:30
  • 1
    This is a good way to use express with react. If you app.use the static build files AFTER you app.use the express router, then express will consult the router first and only thereafter use the static files. Ex you want to use router.get to authenticate a user, then only after that serve the static react build stuff. – sammy Jul 08 '20 at 12:39