简体   繁体   English

Express + Nginx。无法提供静态文件

[英]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 这是我的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 这是我的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 这是我的nginx配置

    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. 但是我在所有脚本上都获得了404。 And an another strange thing is that mime-type on those files is set to text/HTML 另一个奇怪的事情是这些文件上的mime-type设置为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. 我有一个项目,具有相同的项目结构,并且具有相同的配置,但它适用于它,并且在这种情况下它不起作用。

You don't need to configure Nginx and Express to serve static files. 您无需配置Nginx Express来提供静态文件。 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: 在这两种配置中,从/中加载HTML文件:

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

Express as static file server, Nginx as reverse proxy Express作为静态文件服务器,Nginx作为反向代理

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. 快速注意__dirnameexpress.static()使用__dirname Under the hood (actually, it's here on line 65) , Express uses the native Node.js path.resolve() . 引擎盖下(实际上,这是在这里第65行),快速使用本机的Node.js path.resolve() 。 From the docs: 来自文档:

The path.resolve() method resolves a sequence of paths or path segments into an absolute path. path.resolve()方法将一系列路径或路径段解析为绝对路径。

Using path.resolve(__dirname, 'public') actually returns the same as path.resolve('public') . 使用path.resolve(__dirname, 'public')实际上返回与 path.resolve('public') I am thinking that your problem was really telling Nginx to serve static files AND proxy the same requests to Express. 我认为你的问题确实告诉Nginx提供静态文件并代理相同的Express请求。 OK, on to the rest of my answer. 好的,继续我的答案。

Nginx configuration Nginx配置

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作为静态文件服务器,Express作为API服务器

Nginx configuration Nginx配置

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! 希望这可以帮助!

nginx配置文件中删除try_files指令解决了我的问题。

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

I think those two lines are the reasons why it raises an error. 我认为这两行是导致错误的原因。 Can you delete the second one and give it a try? 你能删除第二个并尝试一下吗? Maybe your express app sets the primary static serving folder "node_modules" and that is why the app cannot serve your main script files. 也许你的快递应用程序设置主要静态服务文件夹“node_modules”,这就是应用程序无法提供主脚本文件的原因。

Also, I don't think it is good idea to serve node_modules directory as static folder. 另外,我不认为将node_modules目录作为静态文件夹提供是个好主意。 I think in your setup, "bower" seems more appropriate choice as a javascript package manager. 我认为在您的设置中,“bower”似乎更适合作为javascript包管理器。

Thanks 谢谢

Add a . 添加一个. before the / to denote a relative path: /之前表示相对路径:

<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>

If you have this structure: 如果你有这个结构:

myApp
  app.js
  -public/
     -js/

In app.js you should do like this: app.js你应该这样做:

self.app.use(express.static(path.join(__dirname, 'public')));
staticRoutes.forEach(route=> {
            self.app.use(BASEPATH+route,express.static(path.join(__dirname, 'public')));
        });

where staticRoutes is an array like 其中staticRoutes是一个数组

staticRoutes=[
'services/'
'about/'
];

and in the html (development) 并在HTML(开发)

<script type="text/javascript" src="js/util.js"></script>
<a href="/about">About Us</a>

while when in production is safer using the full path + protocol. 而在生产中使用完整路径+协议更安全。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM