Skip to content

ExpressJS - 静态文件

静态文件(Static files)是无需任何服务器端处理即可直接发送给客户端的资产。这包括 HTML、CSS、客户端 JavaScript、图片、字体等文件。Express 提供了一个强大的内置中间件 express.static 来高效地处理这项任务。

要从某个目录提供文件,你只需将该目录的名称传递给 express.static 中间件即可。一个常见的约定是将此目录命名为 public。

my-app/
├── public/
│ ├── css/
│ │ └── style.css
│ ├── images/
│ │ └── logo.png
│ └── js/
│ └── app.js
├── index.js
└── package.json
import express from 'express';
import path from 'path';
import { fileURLToPath } from 'url';
// ES 模块没有 __dirname,所以我们手动创建它
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();
const PORT = 3000;
// 从 'public' 目录提供静态文件
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', (req, res) => {
// 如果你的 public 文件夹中有一个 index.html,这个路由就不是必需的,
// 因为 express.static 默认会提供它。
res.send('<h1>Welcome to the Main Page!</h1><p>Static assets are served from the /public folder.</p>');
});
app.listen(PORT, () => {
console.log(`Server is running at http://localhost:${PORT}`);
});

现在,public 目录中的任何文件都可以通过域名的根路径访问。Express 将 URL 直接映射到文件:

  • http://localhost:3000/css/style.css 将提供 public/css/style.css 文件。
  • http://localhost:3000/images/logo.png 将提供 public/images/logo.png 文件。
  • 注意:目录名 public 不会成为 URL 的一部分。

你可以多次使用 express.static 中间件来从多个目录提供文件。Express 将按照它们被挂载的顺序在这些目录中查找文件。

// 从 'public' 目录提供服务
app.use(express.static('public'));
// 也从 'assets' 目录提供服务
app.use(express.static('assets'));
// 如果请求 /logo.png,Express 将首先在 'public' 文件夹中查找。
// 如果未找到,则会在 'assets' 文件夹中查找。

为了更好的组织结构或避免命名冲突,你可以创建一个虚拟路径前缀。这意味着文件只能在该特定 URL 前缀下访问,即使文件位于根级目录中。

// 这将把 'public' 目录挂载在 '/static' 路径前缀下。
app.use('/static', express.static('public'));

通过此配置,你现在需要使用 URL 中的 /static 前缀来访问你的静态文件:

  • http://localhost:3000/static/css/style.css
  • http://localhost:3000/static/images/logo.png
  • 使用 path.join():始终使用 path.join(__dirname, 'public') 来创建静态资产目录的绝对路径。这可以避免因应用程序从文件系统不同位置运行而产生的问题。
  • 中间件顺序:将 express.static 放在你的中间件堆栈中靠前的位置,在任何可能拦截静态资产请求的路由处理程序之前。这确保了资产请求能够快速处理,而无需不必要的处理。
  • 生产环境:虽然 express.static 在开发和许多生产场景中表现出色,但对于高流量网站,最佳实践是将静态资产服务卸载到专用的反向代理(如 Nginx)或内容分发网络(CDN)。这可以释放你的 Node.js 服务器,使其专注于处理动态 API 请求,从而显著提高性能和可伸缩性。