Angular 5生产环境页面刷新/直接输URL出404,求无Hash解决方案
这个问题我太熟了!Angular的路由属于前端单页路由,当你刷新页面或者直接在浏览器输入URL时,服务器会默认去寻找对应路径的物理文件,但这些路由路径其实是Angular在前端定义的,服务器上根本不存在对应的文件,所以才会返回404错误。用{useHash: true}确实能绕开这个问题,但URL带#确实不够美观,要实现无Hash的正常访问,核心是让服务器把所有路由请求都转发到Angular的入口文件(一般是index.html),下面给你分几种常见生产服务器的配置方法,你对应自己的情况来就行:
Nginx配置
如果你的生产环境用的是Nginx,修改你的站点配置文件(比如nginx.conf或者sites-available下的对应配置),在server块里添加路由重写规则:
server { listen 80; server_name your-domain.com; # 替换成你的域名 root /path/to/your/angular/dist/folder; # 替换成Angular打包后dist文件夹的路径 index index.html index.htm; location / { # 先尝试访问请求的文件/目录,找不到就转发到index.html try_files $uri $uri/ /index.html; } }
配置完成后重启Nginx,刷新页面或者直接输入URL就能正常访问了。
Apache配置
如果用的是Apache,首先要确保mod_rewrite模块已经启用,然后在Angular打包后的dist文件夹下创建.htaccess文件,写入以下内容:
<IfModule mod_rewrite.c> RewriteEngine On RewriteBase / # 直接访问index.html时不做处理 RewriteRule ^index\.html$ - [L] # 如果请求的不是真实文件 RewriteCond %{REQUEST_FILENAME} !-f # 如果请求的不是真实目录 RewriteCond %{REQUEST_FILENAME} !-d # 把所有不符合的请求转发到index.html RewriteRule . /index.html [L] </IfModule>
另外要确保Apache允许.htaccess生效,在你的站点配置里设置AllowOverride All,比如:
<Directory "/path/to/your/angular/dist/folder"> AllowOverride All </Directory>
重启Apache后就能正常使用无Hash路由了。
IIS配置
如果是Windows IIS服务器,首先需要安装URL Rewrite模块(这个是IIS的扩展,需要单独安装),然后在dist文件夹下创建web.config文件,写入以下内容:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <rewrite> <rules> <rule name="Angular Routes" stopProcessing="true"> <!-- 匹配所有URL --> <match url=".*" /> <conditions logicalGrouping="MatchAll"> <!-- 排除真实存在的文件 --> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <!-- 排除真实存在的目录 --> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> </conditions> <!-- 把请求重写到index.html --> <action type="Rewrite" url="/index.html" /> </rule> </rules> </rewrite> </system.webServer> </configuration>
配置完成后,IIS就会把所有前端路由请求转发到index.html,Angular就能正确解析路由了。
最后检查Angular路由配置
别忘了把之前加的{useHash: true}去掉,确保你的app-routing.module.ts里的路由配置是这样的:
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; // 导入你的组件 const routes: Routes = [ // 你的路由配置 ]; @NgModule({ imports: [RouterModule.forRoot(routes)], // 这里不要加{useHash: true} exports: [RouterModule] }) export class AppRoutingModule { }
这样配置完之后,你就能使用干净的无Hash路由,同时刷新页面或者直接输入URL也不会出现404错误了。
内容的提问来源于stack exchange,提问作者Jossnic

