Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Express + Nginx. Can't serve static files

This is my project folder

/
  public/
    index.html
    main.js
    adaptor.js
    main.css
  node_modules/
    socket.io/
  index.js

and this is static file configuration in my index.js

app.use(express.static(path.join(__dirname, '/public')));
app.use(express.static(path.join(__dirname, '/node_modules')));
app.get('/', (req, res)=>{
    res.sendFile(path.join(__dirname, 'public', '/index.html'));
})

and this is my index.html

  <script src="/socket.io/socket.io.js" charset="utf-8"></script>
  <script src="/adapter.js" charset="utf-8"></script>
  <script src="/main.js" charset="utf-8"></script>

and this is my nginx configuration

    location / {
            # First attempt to serve request as file, then
            # as directory, then fall back to displaying a 404.
            try_files $uri $uri/ /index.html =404;
            proxy_pass http://localhost:8080;
    }

But I am getting 404 on all the scripts. And an another strange thing is that mime-type on those files is set to text/HTML

What am I doing wrong here?

I have a project, with an identical project structure, and it has the same configuration, but it works for it, and it isn't working in this case.

like image 789
relentless-coder Avatar asked Oct 11 '17 15:10

relentless-coder


2 Answers

You don't need to configure Nginx and Express to serve static files. Both are capable of doing the job independently, but it is up to you to choose.

For these examples I am assuming the same file structure provided in your question.

In both configurations, load files from / in HTML:

<script src="/main.js"></script> <!-- loads from myapp/public/main.js -->

Express as static file server, Nginx as reverse proxy

express app

const express = require('express');
const app = express();

app.use(express.static('public')); // notice the absence of `__dirname`, explained later on

// if the request URL doesn't match anything in the 'public' folder,
// it will start searching here next.
app.use(express.static('some_other_folder'));

// from my testing, express will automatically locate index.html if
// it is in a static folder. Declaring a route is not required.

/* 
app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
*/

app.listen(8080);

// GET / => index.html
// GET /main.js => main.js

Quick side note: the use of __dirname in express.static() is not required. Under the hood (actually, it's here on line 65) , Express uses the native Node.js path.resolve(). From the docs:

The path.resolve() method resolves a sequence of paths or path segments into an absolute path.

Using path.resolve(__dirname, 'public') actually returns the same as path.resolve('public'). I am thinking that your problem was really telling Nginx to serve static files AND proxy the same requests to Express. OK, on to the rest of my answer.

Nginx configuration

server {
  listen 8081; # must be different port from Express
  server_name example.com;
  location / {
    # hand ALL requests back to express
    proxy_pass http://localhost:8080; 
  }
}

Nginx as static file server, Express as API server

Nginx configuration

server {
  listen 8081;
  server_name example.com;
  location / {
    root /path/to/website/public;
    index index.html;
    try_files $uri $uri/ @express; # instead of 404, proxy back to express using a named location block;
    # source: https://stackoverflow.com/a/15467555/8436941
  }
  location @express {
    proxy_pass http://localhost:8080;
  }
}

Express app

const express = require('express');
const app = express();

// actually, Nginx has already taken care of static files. You can still define other routes for API functions for example.
app.get('/my/api', (req, res) => {/* query database, etc. */});

app.listen(8080);

Hope this helps!

like image 198
ContinuousLoad Avatar answered Sep 21 '22 12:09

ContinuousLoad


Removing the try_files directive from the nginx configuration file solved the issue for me.

like image 39
Gal Sasson Avatar answered Sep 19 '22 12:09

Gal Sasson