Heroku部署Angular 4应用:刷新/直接访问子路由出现CSP错误求助
嘿,这种问题我之前帮朋友排查过,咱们一步步来拆解:本地跑没问题、Heroku首次启动正常,但直接访问子路由或刷新就炸CSP错误,核心原因基本逃不开两个点:Express服务器的路由 fallback 没配置对,或者CSP规则卡了Angular的运行资源。
一、先把Express的SPA路由 fallback 搞定
Angular是单页应用,所有前端路由本来应该由Angular自己处理,但你直接敲子路由(比如/user/profile)或者刷新页面时,Heroku上的Express服务器会傻呵呵地找对应的后端路由——找不到的话就会返回错误页面/资源,浏览器加载这些错东西自然触发CSP违规。
你得给Express加个兜底路由,步骤如下:
- 打开你的Express入口文件(比如
server.js),先确保静态资源指向Angular打包后的dist目录:
const express = require('express'); const path = require('path'); const app = express(); // 托管Angular打包后的静态文件 app.use(express.static(path.join(__dirname, 'dist/你的应用名称')));
- 然后加个通配路由,把所有非API的请求都转发到Angular的
index.html:
// 关键!所有前端路由请求都交给Angular处理 app.get('*', (req, res) => { res.sendFile(path.join(__dirname, 'dist/你的应用名称/index.html')); });
划重点:这个通配路由必须放在所有API路由的后面,不然你的后端接口请求也会被转发到index.html,那才是真的炸了。
如果之前没加这个配置,服务器处理子路由请求时返回的不是Angular的入口文件,浏览器加载错误内容就会触发CSP报错,这是最常见的问题。
二、再排查CSP配置的坑
如果路由 fallback 已经配好还是报错,那就要看CSP规则是不是太严了:
1. 检查index.html里的meta标签
如果你在index.html里加了CSP的meta标签,比如:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';">
要注意:
- Angular运行时会生成内联脚本和样式,所以必须允许
'unsafe-inline'和'unsafe-eval'(生产环境用AOT编译的话可以去掉'unsafe-eval',但Angular 4的AOT可能还是需要,先加上试试)。 - 如果你的应用用了第三方资源(比如Google Fonts、CDN库),得在对应的src里加域名,比如用了谷歌字体就要加
font-src 'self' fonts.gstatic.com;。
2. 检查Heroku是否自动加了CSP头
有些Heroku插件或者默认配置会偷偷给你加CSP头,和你自己的meta标签冲突。你可以打开浏览器开发者工具的Network标签,看一下请求返回的响应头里有没有多个Content-Security-Policy字段。
如果有冲突,建议删掉index.html里的meta标签,改用Express来设置CSP头,这样更可控:
// 在server.js里全局设置CSP头 app.use((req, res, next) => { res.setHeader( 'Content-Security-Policy', "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; font-src 'self' fonts.gstatic.com;" ); next(); });
三、最后确认下部署流程没出错
别漏了最基础的检查:
- 本地先跑
ng build --prod生成生产环境的dist目录,确保打包没问题。 - Heroku的
package.json里的scripts要包含build命令,比如:
"scripts": { "start": "node server.js", "build": "ng build --prod" }
- 要是让Heroku自动打包的话,
.gitignore可以保留dist目录,同时在Heroku的环境变量里配置好Node和npm版本,确保Angular CLI能正常运行。
总结
先优先搞定Express的路由 fallback,这是SPA部署到Node服务器的经典坑;如果还不行再调CSP规则,别把Angular需要的资源给禁了。
内容的提问来源于stack exchange,提问作者Bromox

