Express-js无法获取我的静态文件,为什么?

359

我已将我的代码简化为最简单的express-js应用程序:

var express = require("express"),
    app = express.createServer();
app.use(express.static(__dirname + '/styles'));
app.listen(3001);

我的目录看起来像这样:

static_file.js
/styles
  default.css

然而,当我访问http://localhost:3001/styles/default.css时,我会收到以下错误:

Cannot GET / styles /
default.css

我正在使用express 2.3.3node 0.4.7。我做错了什么?


请查看以下链接:http://only4ututorials.blogspot.com/2017/05/how-to-serve-static-file-in-express-js.html - Dexter
26个回答

2

Webpack 让事情变得棘手

作为所有其他已经存在的解决方案的补充:

首先:如果您将文件和目录的路径基于当前工作目录 cwd,那么一切都应该像往常一样工作,因为 cwd 是您启动 node(或 npm startyarn run 等)时所在的文件夹。

然而...

如果您正在使用 webpack,则 __dirname 的行为会根据您的 node.__dirname 设置和 webpack 版本而有很大不同:

  1. In Webpack v4, the default behavior for __dirname is just /, as documented here.
    • In this case, you usually want to add this to your config which makes it act like the default in v5, that is __filename and __dirname now behave as-is but for the output file:
      module.exports = {
         // ...
         node: {
           // generate actual output file information
           // see: https://webpack.js.org/configuration/node/#node__filename
           __dirname: false,
           __filename: false,
         }
      };
      
    • This has also been discussed here.
  2. In Webpack v5, per the documentation here, the default is already for __filename and __dirname to behave as-is but for the output file, thereby achieving the same result as the config change for v4.

例子

举个例子,假设:

  • 您想添加静态的public文件夹
  • 它位于您的输出文件夹旁边(通常是dist),并且在dist中没有子文件夹,那么它可能看起来像这样
const ServerRoot = path.resolve(__dirname /** dist */, '..');
// ...
app.use(express.static(path.join(ServerRoot, 'public'))

(重要提示:再次强调,这与您的源文件位置无关,只考虑输出文件所在的位置!)

更高级的Webpack场景

如果您有多个入口点位于不同的输出目录中,则情况会变得更加复杂,因为对于相同文件,__dirname可能对于每个entry中的输出文件(即合并到该源文件的输出文件的位置)是不同的,更糟糕的是,同一源文件可能会合并到多个不同的输出文件中。

您可能希望避免这种情况,或者如果无法避免,则使用Webpack来管理和注入正确的路径,可能通过DefinePluginEnvironmentPlugin实现。


2

使用__dirname的问题在于,__dirname返回的是当前文件的路径,而不是项目文件的路径。 此外,如果您使用动态头部,每个页面将在不同的路径中查找静态文件,这将无法正常工作。 对我来说最好的方法是将__dirname替换为process.cwd(),它始终表示项目文件的路径。

app.use(express.static(process.cwd() + '/public'));

在你的项目中:

link rel="stylesheet" href="/styles/default.css"

请参见:process.cwd()和__dirname有什么区别?


1
尝试使用'./public'代替__dirname + '/public'。同样,尝试使用process.cwd() + '/public'。 有时候我们会迷失在正在处理的目录中,避免假设文件位于我们告诉express的位置是很好的选择。 同样,避免假设在依赖的深处路径在每个级别上都被解释为相同的方式。

始终尝试使用__dirname,除非您有一个不需要一直访问项目文件的情况。 - asciidude

1
我找到了我的CSS文件并添加了一个路由:
app.get('/css/MyCSS.css', function(req, res){
  res.sendFile(__dirname + '/public/css/MyCSS.css');
});

然后它似乎工作了。

1
我不建议使用这种方法,因为你应该使用ExpressJS的.use()express.static()方法来发送你正在提供文件的位置。否则,你将在公共目录中拥有每个文件的路由器,这会增加很多维护开销。 - Sgnl
这是一个解决方法,但我认为它并不合适。如果你有很多CSS和JS文件,你该如何维护它们? - arshovon

1
如果您的设置
myApp
  |
  |__ public
  |     |
  |     |__  stylesheets
  |     |     |
  |     |     |__ style.css
  |     |
  |     |___ img
  |           |
  |           |__ logo.png
  |
  |__ app.js

然后,将其放入app.js中。
app.use('/static', express.static('public'));

请参考您的style.css文件:(在某个.pug文件中):
link(rel='stylesheet', href='/static/stylesheets/style.css')

为什么要引入重命名步骤public -> static?我认为这只会增加更多混淆的信息。但是再说一遍,间接通常是一件好事... - masterxilo

1

尝试使用http://localhost:3001/default.css访问它。

   app.use(express.static(__dirname + '/styles'));

实际上你给它的是文件夹的名称,例如styles而不是你的子网址。


1
app.use(express.static(__dirname+'/'));

这对我有用,我尝试使用公共目录但是没有成功。 但在这种情况下,我们给整个目录的静态文件访问权限,希望能够帮到你!


0
  1. 在Nodejs项目文件夹中创建名为“public”的文件夹。
  2. 将index.html文件放入Nodejs项目文件夹中。
  3. 将所有脚本和CSS文件放入public文件夹中。
  4. 使用app.use(express.static('public'));

  5. 并在index.html中将脚本的路径更正为<script type="text/javascript" src="/javasrc/example.js"></script>

现在一切都正常工作了。


0
除此之外,确保静态文件路径以/开头(例如... /assets/css)...以便在主目录(/main)上方的任何目录中提供静态文件。

2
除了上面的内容之外,你的回答中要说明它(如果必要,要给发布者以功劳)。SO经常更改答案的顺序,以便所有答案都能被看到,而不仅仅是前几个。我们不知道你在说什么。 - Zachary Kniebel

0

这对我有用:

服务器:

app.use(express.static("public"));

客户:

<link href="css/styles.css" rel="stylesheet">
<img src="images/210504.png">

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接