Sivo 悉见

带路由的应用必须以index.html作为后备页面

匿名 · 更新于 2017/9/28

Routed apps must fallback to index.html

Angular应用很适合用简单的静态HTML服务器提供服务。 我们不需要服务端引擎来动态合成应用页面,因为Angular会在客户端完成这件事。

如果该应用使用Angular路由器,我们就必须配置服务器,让它对不存在的文件返回应用的宿主页(index.html)。

带路由的应用应该支持“深链接”。 所谓深链接就是指一个URL,它用于指定到应用内某个组件的路径。 比如,http://www.mysite.com/heroes/42就是一个到英雄详情页面的深链接,用于显示id: 42的英雄。

当用户从运行中的客户端应用导航到这个URL时,这没问题。 Angular路由器会拦截这个URL,并且把它路由到正确的页面。

但是,当从邮件中点击链接或在浏览器地址栏中输入它或仅仅在英雄详情页刷新下浏览器时,所有这些操作都是由浏览器本身处理的,在应用的控制范围之外。 浏览器会直接向服务器请求那个URL,路由器没机会插手。

But clicking a link in an email, entering it in the browser address bar, or merely refreshing the browser while on the hero detail page — all of these actions are handled by the browser itself, outside the running application. The browser makes a direct request to the server for that URL, bypassing the router.

静态服务器会在收到对http://www.mysite.com/的请求时返回index.html,但是会拒绝对http://www.mysite.com/heroes/42的请求, 并返回一个404 - Not Found错误,除非,我们把它配置成转而返回index.html

后备页面配置范例

没有一种配置可以适用于所有服务器。 后面这些部分会描述对常见服务器的配置方式。 这个列表虽然不够详尽,但可以为你提供一个良好的起点。

开发服务器

content_copyhistoryApiFallback: {
  disableDotRule: true,
  htmlAcceptHeaders: ['text/html', 'application/xhtml+xml']
}

生产服务器

content_copyRewriteEngine On
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]

# If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html
content_copytry_files $uri $uri/ /index.html;
  • IIS:往web.config中添加一条重写规则,类似于这里

content_copy
  1. <system.webServer>
  2. <rewrite>
  3. <rules>
  4. <rule name="Angular Routes" stopProcessing="true">
  5. <match url=".*" />
  6. <conditions logicalGrouping="MatchAll">
  7. <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
  8. <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
  9. </conditions>
  10. <action type="Rewrite" url="/src/" />
  11. </rule>
  12. </rules>
  13. </rewrite>
  14. </system.webServer>
content_copy"rewrites": [ {
  "source": "**",
  "destination": "/index.html"
} ]

l