Angular部署在Apache子目录下.htaccess失效问题排查与解决
问题分析与解决
一、硬刷新404的原因
你在根目录配置的.htaccess规则,最后一条RewriteRule ^ /index.html会将所有不存在的资源请求跳转到根目录的index.html,但你的Angular应用入口是/foo/index.html。当你刷新site.com/foo/items这类路由时,服务器找不到对应的物理文件,就会跳去根目录的index.html(而非你的应用入口),导致404错误。
而你在foo目录内创建foo子目录并放置应用后刷新正常,是因为此时Angular应用的base href自动适配了子目录路径(比如/foo/foo/),同时如果根目录没有index.html,Apache会尝试加载子目录的入口文件,刚好匹配到你的应用,但这是偶然生效的非常规状态。
二、解决方法
有两种可靠的配置方式:
方式1:在foo目录下添加专属.htaccess
在/var/www/html/foo目录新建.htaccess文件,内容如下:
RewriteEngine On RewriteBase /foo/ # 存在的文件或目录直接访问 RewriteCond %{REQUEST_FILENAME} -f [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^ - [L] # 不存在的请求转发到当前目录的index.html RewriteRule ^ index.html
这个规则会让foo目录下所有不存在的请求,都转发到/foo/index.html(你的Angular应用入口),同时不会影响根目录和bar1、bar2目录的原有规则。
方式2:修改根目录.htaccess,针对foo目录做规则
如果你不想在foo目录新增.htaccess,可以修改根目录的规则,仅对foo路径的请求做适配:
RewriteEngine On RewriteBase / # 处理foo目录的Angular路由 RewriteCond %{REQUEST_URI} ^/foo/ RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d RewriteRule ^foo/(.*)$ /foo/index.html [L] # 其他目录的原有规则:存在的文件/目录直接访问 RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR] RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d RewriteRule ^ - [L] # 根目录自身的请求转发(如果根目录有独立应用则保留,否则可删除) # RewriteRule ^ /index.html
三、将foo内容移至根目录的可行性
完全可行,保留根目录现有的.htaccess规则即可,但需要注意两点:
- Angular构建时指定
base href为/,执行命令:ng build --base-href /,确保路由匹配正确。 bar1、bar2目录下的RewriteEngine Off的.htaccess依然有效,会阻止根目录规则在这些目录下生效,不会影响第三方应用运行。
内容的提问来源于stack exchange,提问作者friendlynihilist
相关产品推荐
相关产品推荐

