Express 静态资源托管详解:从本地 HTML 到 express.static()

学习前端时,我们通常直接在 VSCode 中编写 HTML、CSS 和 JavaScript 文件,然后通过浏览器打开页面。

但学习 Express 时,却需要使用 express.static() 托管静态资源。

这就产生了几个疑问:浏览器明明可以直接打开 HTML,为什么还需要服务器?静态资源托管是什么? **express.static()**又是如何工作的?

本文从浏览器访问文件的原理出发,介绍 Express 静态资源托管的基本使用、多目录托管和路径前缀。

一、什么是静态资源?

静态资源是指服务器可以直接提供给客户端的文件,例如:

  • HTML:网页结构

  • CSS:网页样式

  • JavaScript:网页交互逻辑

  • 图片、字体等资源文件

假设项目目录如下:

复制代码
my-project/
├── app.js
└── public/
    ├── index.html
    ├── style.css
    ├── index.js
    └── logo.png

其中 public 文件夹保存网站需要的静态资源。

静态资源托管,就是让服务器根据客户端的 HTTP 请求,找到并返回对应的静态文件。

二、为什么需要静态资源托管?

1. 浏览器不是可以直接打开 HTML 吗?

当然可以。

假设电脑中有一个文件:

复制代码
D:\project\index.html

双击打开后,浏览器地址栏可能显示:

复制代码
file:///D:/project/index.html

这里使用的是 file:// 协议。

浏览器直接读取本机文件,不需要经过 HTTP 服务器。

但如果其他用户想访问这个网页,就会出现问题。

因为其他用户打开相同的本地路径时,浏览器会去他自己的电脑寻找文件,而不是访问你的电脑。

2. 如何让其他用户访问网页?

这时就需要 HTTP 服务器。

复制代码
用户浏览器
    │
    │ HTTP 请求 index.html
    ▼
  Web 服务器
    │
    │ 查找对应的文件
    ▼
public/index.html
    │
    │ 返回 HTML 内容
    ▼
用户浏览器渲染页面

服务器通过 HTTP 将网页文件提供给客户端,客户端不需要事先拥有这些文件。

值得注意的是,服务器也可以运行在自己的电脑上,例如访问 http://localhost:3000。

3. VSCode 的 Live Server 又是什么?

如果使用 VSCode 的 Live Server 插件,打开的地址一般是:

复制代码
http://127.0.0.1:5500/index.html

这里已经使用了 HTTP 协议。

实际上,Live Server 已经帮我们在本机启动了一个 HTTP 服务器。

因此:

访问方式 工作原理
双击 HTML 浏览器直接读取本地文件
VSCode Live Server 插件启动 HTTP 服务器提供文件
Express 静态托管 Node.js 服务器通过 HTTP 提供文件

它们都可以让浏览器显示网页,但文件获取方式不同。

三、express.static() 是什么?

**express.static()****是 Express 内置的中间件工厂函数,可以让 Express 自动向客户端提供指定目录下的静态文件。**帮你省去手动编写静态资源路由、读取文件和返回文件的代码。

基本用法:

复制代码
app.use(express.static('public'))

拆开理解:

1. express.static('public')

创建一个静态资源中间件,指定 public 为静态资源目录。

2. app.use()

将中间件注册到 Express 应用中,让请求经过它处理。

当浏览器请求文件时,Express 会自动查找对应资源并返回,无需为每个文件单独编写路由。

四、express.static() 基本使用

完整代码:

javascript 复制代码
const express = require('express')
const path = require('path')

const app = express()

// 托管 public 文件夹
app.use(express.static(
  path.join(__dirname, 'public')
))

app.listen(3000, () => {
  console.log('服务器启动成功')
})

假设项目目录:

复制代码
my-project/
├── app.js
└── public/
    ├── index.html
    ├── css/
    │   └── style.css
    ├── js/
    │   └── app.js
    └── images/
        └── logo.png

服务器启动后,可以通过以下地址访问:

浏览器访问路径 实际文件位置
/index.html public/index.html
/css/style.css public/css/style.css
/js/app.js public/js/app.js
/images/logo.png public/images/logo.png

例如:

复制代码
http://localhost:3000/images/logo.png

Express 就会查找:

复制代码
public/images/logo.png

找到后,自动返回图片内容。

注意:默认情况下,URL 不需要包含 public**,因为** public****是指定的静态资源根目录,而不是 URL 路径的一部分。

另外,使用 path.join(__dirname, 'public') 是为了确保静态资源路径以当前 JS 文件所在目录为基准,避免终端工作目录变化导致找不到文件。

五、如何托管多个静态资源目录?

实际项目中,静态文件可能分散在多个目录。

例如:

复制代码
my-project/
├── app.js
├── public/
│   └── index.html
└── files/
    └── logo.png

我们可以多次使用 express.static():

复制代码
app.use(express.static('public'))

app.use(express.static('files'))

这样就能同时访问两个目录中的资源。

例如:

复制代码
http://localhost:3000/index.html
http://localhost:3000/logo.png

Express 会依次在注册的静态目录中查找文件。

如果两个目录中存在相同名称的文件呢?

假设:

复制代码
public/logo.png
files/logo.png

此时访问:

复制代码
http://localhost:3000/logo.png

Express 会优先查找 public 目录。

如果找到了文件,就直接返回;如果没有找到,再继续查找后面的 files 目录。

因此,多个静态资源目录的注册顺序会影响文件查找优先级,先注册的目录优先。

六、什么是静态资源路径前缀?

前面的例子中:

复制代码
app.use(express.static('public'))

浏览器直接通过:

复制代码
http://localhost:3000/logo.png

访问 public/logo.png。

但如果我们希望 URL 中明确带上 /public,例如:

复制代码
http://localhost:3000/public/logo.png

就需要设置路径前缀。

代码如下:

复制代码
app.use('/public', express.static('public'))

两个部分的作用:

  • '/public':指定 URL 访问前缀。

  • express.static('public'):指定实际存放静态文件的目录。

访问过程:

复制代码
浏览器请求:
/public/images/logo.png
         ↓
匹配 URL 前缀 /public
         ↓
剩余路径 /images/logo.png
         ↓
在 public 目录下查找
         ↓
public/images/logo.png

注意:前面的 /public****是 URL 前缀,后面的 **'public'**是服务器文件夹名称,两者并不必须相同。

例如:

复制代码
app.use('/static', express.static('public'))

就可以通过:

复制代码
http://localhost:3000/static/logo.png

访问实际位于 public/logo.png 的文件。

七、静态资源托管和动态接口有什么区别?

Express 不仅可以提供静态资源,还可以处理动态请求。

例如:

复制代码
const express = require('express')
const app = express()

// 静态资源
app.use(express.static('public'))

// 动态接口
app.get('/api/user', (req, res) => {
  res.json({
    name: '张三',
    age: 20
  })
})

app.listen(3000)

它们的区别:

对比 静态资源托管 动态接口
主要用途 提供已有文件 根据请求生成数据
常用方式 express.static() app.get() 等路由
返回内容 HTML、CSS、JS、图片等 JSON、文本等
处理过程 查找并返回文件 执行业务逻辑并返回响应

例如,访问 /logo.png 可以直接返回已有图片,而访问 /api/user 则执行对应的路由函数,生成 JSON 响应。

八、和 Vue、React 项目有什么关系?

学习 Webpack、Vite 时,我们知道前端项目可以通过:

复制代码
npm run build

生成生产环境资源。

例如:

复制代码
dist/
├── index.html
└── assets/
    ├── index-xxx.js
    └── index-xxx.css

这些构建产物本质上也是静态资源。

我们可以通过 Express 提供它们:

复制代码
const express = require('express')
const path = require('path')

const app = express()

app.use(express.static(
  path.join(__dirname, 'dist')
))

app.listen(3000)

现在浏览器就可以通过 HTTP 访问构建后的网页。

不过,如果是使用前端路由的 SPA 项目,例如 React Router 的 History 路由模式,通常还需要配置页面回退规则,让非静态资源的前端路由请求返回 index.html。

实际生产部署也常使用 Nginx、CDN 或静态托管平台,并不是必须使用 Express。

九、总结

理解 express.static(),需要掌握四个关键点:

  1. 静态资源托管: 让服务器通过 HTTP 向浏览器提供 HTML、CSS、JS、图片等文件。

  2. express.static()****: Express 提供的静态资源中间件,可以自动查找并返回指定目录中的文件。

  3. 多个目录: 可以多次注册 express.static(),Express 按注册顺序查找资源。

  4. 路径前缀: 通过 app.use('/static', express.static('public')),可以让资源通过指定 URL 前缀访问。

一句话总结: **express.static()**的作用,就是把服务器上的某个文件夹映射成可以通过 HTTP 访问的静态资源路径,让浏览器能够请求并获取其中的 HTML、CSS、JS、图片等文件,而不需要开发者为每个文件单独编写路由。

相关推荐
yyuuuzz1 小时前
云服务器部署 web 项目的进程常驻记录
运维·服务器·前端·阿里云·云计算·aws
IT_陈寒1 小时前
一文搞懂React的核心概念
前端·人工智能·后端
薛一半2 小时前
Redux实战:组件状态管理全解析
开发语言·前端·javascript·react.js
风骏时光牛马2 小时前
功能模块性能测试用例验证
前端
对空六课3 小时前
两个统计平台数据不同:用同一时间窗和事件样本做差异定位
大数据·前端·网络·数据库
lpfasd12311 小时前
node-sass 停止维护!老项目迁移 Dart Sass 完整教程
前端·rust·sass
Data analyse45613 小时前
rnweb 回放数据量太大怎么办?分片存储与断点续传的实现思路
前端·网络·算法·数据分析
xiaogai_gai14 小时前
金蝶收料通知单查询策略实战教程:从源系统拉取到中间层落地的完整路径
java·前端·数据库
环境栈笔记14 小时前
指纹浏览器 WebRTC 怎么设置?从 ICE 候选、代理出口到功能验证
前端·人工智能·后端·自动化