Node.js Express应用无法加载CSS静态文件问题求助
问题核心原因
CSS加载失败、访问CSS地址显示纯文本,是静态资源配置与前端引用路径不匹配+动态路由拦截静态资源请求共同导致的,和CORS、浏览器缓存无关:
- 你配置
app.use(express.static(path.join(__dirname, '/public')));的作用是将public文件夹设为静态资源根目录,访问该目录下的文件不需要加/public前缀,直接写根路径+文件名即可。但你在ejs里写的CSS引用路径是/public/styles.css,路径完全错误。 - 你额外配置的
app.use("/styles", express.static(__dirname + '/styles'));是无效配置,你的项目根目录下根本不存在styles文件夹,CSS实际存放在public目录下。 - 你把
views模板文件夹设为了静态资源目录,存在源码泄露风险,且完全没必要。 - 产品路由中
router.get('/:book', product_controller.product_details);是一级泛匹配动态路由,你写错路径的CSS请求/public/styles.css不会走到静态资源处理逻辑,会被这个路由直接拦截,返回产品接口的内容,所以你访问CSS地址看到的是纯文本,不是合法的CSS文件,浏览器自然无法加载样式。 index.ejs里的<base href="/">写在了CSS引用标签之后,不会对前面的资源引用生效;同时你引用的根路径app.js不存在于静态资源目录,后续也会报404错误。
修复步骤
- 清理app.js中无效的静态资源配置
只保留public目录作为唯一静态资源入口,删掉无效的views、styles目录挂载配置,注意静态资源配置必须放在业务路由挂载代码之前,避免请求被路由优先拦截。修正后的app.js核心配置:
const express = require('express'); const bodyParser = require('body-parser'); const product = require('./routes/product.routes'); const app = express(); const path = require('path'); const cors = require('cors'); app.set('views', __dirname + '/views'); app.set('view engine', 'ejs') app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: false})); app.use(cors({ origin: '*' })); // 只保留这一行静态资源配置即可 app.use(express.static(path.join(__dirname, 'public'))); // 删掉以下两行无效配置 // app.use(express.static(path.join(__dirname, 'views'))); // app.use("/styles", express.static(__dirname + '/styles')); app.use('/product', product); let port = 3000; app.listen(port, () => { console.log('Server is up and running on port number ' + port); });
- 修正index.ejs中的资源引用
- 把
<base href="/">移到head标签最开头,保证所有资源引用都基于根路径 - 将CSS引用路径改为
/styles.css,不需要带public前缀 - 删掉不存在的根路径app.js引用,后续如果要加前端js,放到public目录下再按根路径引用即可
修正后的index.ejs代码:
<html lang="en"> <head> <base href="/"> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>HTML 5 Boilerplate</title> <link rel="stylesheet" type="text/css" href='/styles.css'/> </head> <body> <h1>BookBooker</h1> <h2>A library app for personal use.</h2> <form action="/create" method="POST"> <input type="text" placeholder="Writer" name="name" /> <input type="text" placeholder="Book" name="book" /> <button type="submit">Submit</button> </form> </body> </html>
- 验证效果
修改完成后重启Node服务,直接访问http://localhost:3000/styles.css会返回正确的CSS文件,响应头Content-Type自动为text/css,打开页面即可看到正常加载的样式。
额外注意事项
express.static挂载的静态资源目录,对外访问时不需要写目录本身的名字,比如public/styles.css访问路径就是/styles.css,如果后续在public下新建css子文件夹存放public/css/styles.css,访问路径直接写/css/styles.css即可,不需要修改服务端配置。- 不要把存放模板的views目录设为静态资源目录,否则用户可以直接下载你的ejs模板源码,存在安全风险。
- 带通配符/动态参数的路由尽量不要放在一级路径,避免拦截静态资源或其他正常接口请求,可以给这类接口加统一前缀,比如把产品详情接口改成
/product/detail/:book,就不会误拦截根路径下的静态资源请求。
内容的提问来源于stack exchange,提问作者Jammy Piece
相关产品推荐
相关产品推荐

