Express.js不使用static静态文件夹时,HTML无法加载外部CSS/JS的问题
问题
原本通过Express.js的app.use(express.static("public"))配置静态文件夹后,public目录下的index.html可以正常加载css/style.css和js/tool.js。现在移除了静态文件夹配置,改用app.get("/")返回index.html,但HTML无法加载外部CSS和JS。
尝试过多种文件路径写法:
<link rel="stylesheet" href="public/css/style.css"> <link rel="stylesheet" href="/public/css/style.css"> <link rel="stylesheet" href="./css/style.css">
以及tool.js的类似路径,甚至把style.css和tool.js与index.html放在同一目录,用<link rel="stylesheet" href="style.css">也无效。报错信息包括:
Refused to apply style from 'https://www.example.com/css/style.css' because its MIME type ('text/html') is not a supported stylesheet MIME type... GET https://www.example.com/js/tool.js net::ERR_ABORTED 404 (Not Found)
已查阅相关问题但未解决,需要在不使用app.use(express.static("public"))的前提下解决该问题。
解决方法
1. 为单个资源编写独立路由
移除静态中间件后,Express不会自动处理静态资源请求,必须为每个资源路径单独配置路由,读取对应文件并返回,同时设置正确的MIME类型。
示例代码:
const express = require('express'); const path = require('path'); const app = express(); // 返回首页HTML app.get('/', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'index.html')); }); // 处理CSS资源请求 app.get('/css/style.css', (req, res) => { res.setHeader('Content-Type', 'text/css'); res.sendFile(path.join(__dirname, 'public', 'css', 'style.css')); }); // 处理JS资源请求 app.get('/js/tool.js', (req, res) => { res.setHeader('Content-Type', 'application/javascript'); res.sendFile(path.join(__dirname, 'public', 'js', 'tool.js')); }); app.listen(3000, () => console.log('Server running on port 3000'));
此时HTML中使用绝对路径引用资源即可:
<link rel="stylesheet" href="/css/style.css"> <script src="/js/tool.js"></script>
2. 正则匹配批量处理资源路由
如果资源数量较多,可通过正则匹配资源路径前缀,自动读取对应文件并设置MIME类型,避免逐个编写路由。需要先安装mime-types包来自动识别MIME类型:npm install mime-types
示例代码:
const express = require('express'); const path = require('path'); const mime = require('mime-types'); const app = express(); app.get('/', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'index.html')); }); // 匹配所有/css/、/js/开头的资源请求 app.get(/^\/(css|js)\/.*$/, (req, res) => { const filePath = path.join(__dirname, 'public', req.path); const contentType = mime.lookup(filePath); if (contentType) { res.setHeader('Content-Type', contentType); } res.sendFile(filePath, (err) => { if (err) { res.status(404).send('Resource not found'); } }); }); app.listen(3000, () => console.log('Server running on port 3000'));
HTML中的资源路径写法和第一种方法一致,只要请求路径与文件目录结构对应即可。
3. 内联CSS/JS代码(简易方案)
如果资源内容较少,可直接将CSS和JS代码内联到index.html中,无需额外的资源请求:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>首页</title> <style> /* 把style.css的内容直接写在这里 */ body { margin: 0; padding: 2rem; font-family: Arial, sans-serif; } </style> </head> <body> <h1>Hello World</h1> <script> // 把tool.js的内容直接写在这里 console.log('内联脚本已加载'); </script> </body> </html>
此方法无需配置任何资源路由,适合小型项目或快速测试场景。
内容的提问来源于stack exchange,提问作者EricandWeb

