GitHub Actions 部署 Angular 18 后为何出现 404?
结论
404 是上传目录选错导致的。日志中已经给出了首页的实际位置:
dist/webapp/browser/index.html
但 workflow 上传的是整个 ./dist/,所以 GitHub Pages 部署包的根目录结构如下:
webapp/
└── browser/
└── index.html
Pages 会在部署包根目录查找 index.html。由于根目录下没有这个文件,访问 https://mr-olufsen.github.io/webapp/ 时就会返回 404。
把上传路径改为:
path: ./dist/webapp/browser
这个项目部署在带有 /webapp/ 前缀的 URL 下,构建时还要设置:
ng build --base-href /webapp/
缺少这项配置时,即使首页可以打开,JS、CSS 等静态资源也可能从域名根目录加载,从而出现资源 404。
为什么 workflow 成功,页面却仍然 404
actions/deploy-pages 显示成功,只代表 artifact 已经上传并交给 GitHub Pages。它不会检查部署包根目录是否包含 index.html。
日志里的两段信息足以定位问题:
Output location: /home/runner/work/webapp/webapp/dist/webapp
以及:
./webapp/browser/index.html
上传 ./dist/ 后,index.html 在部署包内仍然隔着 webapp/browser/ 两层目录。GitHub Pages 不会自动进入这个子目录寻找首页。
Angular 18 使用 application builder 时,浏览器端文件通常生成在 dist/<project-name>/browser/。具体位置要以构建日志和 angular.json 中的 outputPath 为准,不能默认产物就在 dist/ 根目录。
推荐修改
下面沿用原 workflow 中的 action 主版本,只修改与这次故障有关的配置:
name: Deploy Angular to GitHub Pages
on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18.x
cache: npm
cache-dependency-path: package-lock.json
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build -- --base-href /webapp/
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v2
with:
path: ./dist/webapp/browser
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
如果仓库名称不是 webapp,需要分别修改以下两处:
run: npm run build -- --base-href /实际仓库名/
path: ./dist/实际项目输出目录/browser
base-href 对应 GitHub Pages URL 中的仓库路径,artifact 路径则对应 Angular 的实际输出目录。两者经常同名,但并不要求一致。
也可以在 angular.json 中固定 baseHref
如果项目始终部署在 /webapp/ 下,可以把配置写进 angular.json,然后在 workflow 中使用普通的构建命令:
{
"projects": {
"webapp": {
"architect": {
"build": {
"configurations": {
"production": {
"baseHref": "/webapp/"
}
}
}
}
}
}
}
构建命令为:
npm run build
这样可以避免某个 workflow 遗漏 --base-href。如果应用还要部署到域名根目录或其他子路径,使用命令行参数会更灵活。
部署前检查产物
可以在上传 artifact 前加入检查步骤,确认上传目录内直接包含首页:
- name: Verify build output
run: |
test -f ./dist/webapp/browser/index.html
ls -la ./dist/webapp/browser
需要检查的是:
./dist/webapp/browser/index.html
不是:
./dist/index.html
上传 ./dist/webapp/browser 后,artifact 根目录应类似:
index.html
main-*.js
polyfills-*.js
styles-*.css
favicon.ico
如果 index.html 仍在 webapp/browser/ 这样的子目录里,说明上传路径还没有指向静态站点的根目录。
如果只有刷新子路由时出现 404
如果首页已经可以打开,但直接访问或刷新下面这样的 Angular 路由仍然返回 404:
https://mr-olufsen.github.io/webapp/settings
原因与首页 404 不同。GitHub Pages 是静态文件服务,不会像应用服务器一样把任意路径回退到 index.html。
一种处理方法是使用 hash 路由,将地址改为:
https://mr-olufsen.github.io/webapp/#/settings
Angular 路由可以这样配置:
provideRouter(routes, withHashLocation())
另一种方法是在构建后把 index.html 复制为 404.html:
- name: Build
run: |
npm run build -- --base-href /webapp/
cp ./dist/webapp/browser/index.html ./dist/webapp/browser/404.html
是否采用 404.html,要根据项目的路由、重定向和搜索引擎收录要求决定。如果只要求在纯静态托管环境中可靠运行,hash 路由通常更直接。
还需要确认的 Pages 设置
在仓库的 Settings > Pages 中,部署来源应选择 GitHub Actions。如果 Pages 使用分支发布模式,即使 workflow 完成了 artifact 部署流程,仓库实际展示的内容也可能来自其他来源。
原 workflow 还监听了 pull_request。正式站点通常只需在代码推送到 main 时部署,同时保留手动触发,避免多个提交或拉取请求争用同一个 Pages 环境。
action 版本可以根据仓库当前支持情况另行升级,但这不是本次 404 的原因。日志已经表明 artifact 上传和部署均已成功。
备注:内容仅供参考。
