web-dev-qa-db-ja.com

Angular Html5モードが有効なUiルーターを使用するとページのリロードが失敗する

Angular UI Router in my angular appを使用していますが、HTML5モードを有効にして、構成で$ locationProviderを使用してURLから#を削除しました。

var app = angular.module('openIDC', ['ui.router']);
app.config(function($urlRouterProvider, $stateProvider, $locationProvider) {

    $locationProvider.html5Mode(true);

    $urlRouterProvider.otherwise('/');

    $stateProvider
    .state('home', {
        url: '/',
        templateUrl: 'views/home.html',
        controller: 'HomeController'
    })
    .state('login', {
        url: '/login', 
        templateUrl: 'views/login.html',
        controller: 'LoginController'
    })
});

また、index.htmlファイルにも<base href="/" />タグを設定しました。ルーティングは正常に機能し、ページに移動して#を削除できますが、ブラウザーの再読み込みボタンを使用してページを更新すると、404エラー応答が表示されます。

enter image description here

なぜこれが起こっているのか、どうすれば修正でき、適切なURLを使用できるようにHTML5モードを有効にできるのか

15
Kasun Kodagoda

Kasun、これが発生している理由は、サブルートの1つからページを更新しようとしているためです(ui-routerとは関係ありません)。

基本的にwww.yourdomain.com/をリクエストした場合、サーバーはindex.htmlを返すように設定されている可能性があります。これにより、angularアプリがブートストラップされます。アプリが読み込まれると、以降のURLの変更にはhtml5Modeを考慮に入れ、ui-routerを介してページを更新します。

ページをリロードすると、angularアプリはまだロードされていないため、有効ではなくなりました。したがって、サブルート(例:www.yourdomain.com/someotherpage)をロードしようとすると、サーバーが/someotherpageの処理方法を認識していないため、404またはその他のエラーが返される可能性があります。

あなたがする必要があるのは、あなたのangular app for allルートを返すようにサーバーを設定することです。私は主にnode/expressを使用するので、私は次のようにします:

app.get('*', function(req, res, next) {
    // call all routes and return the index.html file here
}

注:私は通常、このようなものを最終的なキャッチオールとして使用しますが、静的ファイル、Webクローラー、およびその他の特定のルートを要求するようなもののために、その上に他のルートも含めます取り扱いました

12
Matt Way

サーバー側でURL書き換えを設定する必要があります

apacheの場合は次のようになります。

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.html

.htaccessファイル(必ずmod_rewrite Apacheモジュールが有効になっています)

そしてnginxのためにこのような設定:

location / {
    ....
    try_files $uri $uri/ /index.html =404;
}
9
Bogdan Savluk

IIS-まだここには表示されませんでした-これが私のやり方です。URLRewrite 2.0がインストールされていることを確認してください。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="AngularJS Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>`
4
Mike Jouwstra

最初に.htaccessファイルを作成し、次にこれらのコードをコピーして貼り付けます

<ifModule mod_rewrite.c>
     RewriteEngine on

    # Don't rewrite files or directories
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]


    RewriteRule ^ your root folder/index.html [L]
      </ifModule>


<base url="/"></base> in index.html file
3

これがなぜ起こっているのか詳細に説明することはできませんが、この問題を解決する方法を説明できます。そこで、SpringMvcバックエンドにUrlRewriterFilterを使用しました。 Angular一般的なモジュール構成:

var app = angular.module('ilonaChatGeneralModule', 
    [
        'ui.router'
    ]);

app.config(function($locationProvider){
    $locationProvider.html5Mode(true);
});

app.config(function($stateProvider, $urlRouterProvider) {

    $urlRouterProvider.otherwise('/');

    var home = ['/', {
        url: '/',
        templateUrl: 'views/userlist.html'
    }];

    var login = ['login', {
        url: '/login',
        templateUrl: 'views/login.html'
    }];

    var privateRoom = ['privateroom', {
        url: '/privateroom',
        templateUrl: 'views/privateroom.html'
    }];

    $stateProvider
        .state(home)
        .state(login)
        .state(privateRoom)
        ;
});

私のホームページ、index.html:

<html ng-app="ilonaChatGeneralModule"  ng-controller="ilonaChatGeneralCtrl">
<head>
    <base href="/">
    ...

</head>
<body>
<div>
    <div ui-view=""></div>
</div>
</body>
</html>

これはフロントエンドです。 UrlRewriteFilterを使用したバックエンドの場合、次のmaven依存関係で取得できます。

  <dependency>
        <groupId>org.tuckey</groupId>
        <artifactId>urlrewritefilter</artifactId>
        <version>4.0.3</version>
    </dependency>

次の方法でSpringMVC WebAppInitializerに追加しました。

    package com.sbk.config;

    import org.springframework.context.ApplicationContext;
    import org.springframework.web.context.ContextLoaderListener;
    import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
    import org.springframework.web.filter.CharacterEncodingFilter;
    import org.springframework.web.servlet.DispatcherServlet;
    import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
    import org.tuckey.web.filters.urlrewrite.UrlRewriteFilter;

    import javax.servlet.*;
    import Java.nio.charset.StandardCharsets;
    import Java.util.EnumSet;

    public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {   
        private static final String URL_REWRITE_FILTER_NAME = "urlRewrite";
        private static final String URL_REWRITE_FILTER_MAPPING = "/*";

...
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {
            super.onStartup(servletContext);

            FilterRegistration.Dynamic urlReWrite = servletContext.addFilter(URL_REWRITE_FILTER_NAME, new UrlRewriteFilter());
            EnumSet<DispatcherType> urlReWriteDispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);
            urlReWrite.addMappingForUrlPatterns(urlReWriteDispatcherTypes, true, URL_REWRITE_FILTER_MAPPING);
        }
    }

このフィルターには、ur WEB-INFディレクトリーの下のurlrewrite.xmlファイルが必要です(構成可能ですが、デフォルトの場所-ここにあるようです)。このファイルの内容:

<!DOCTYPE urlrewrite
        PUBLIC "-//tuckey.org//DTD UrlRewrite 2.6//EN"
        "http://www.tuckey.org/res/dtds/urlrewrite2.6.dtd">

<urlrewrite>

    <rule>
        <from>/login$</from>
        <to>index.html</to>
    </rule>

    <rule>
        <from>/privateroom$</from>
        <to>index.html</to>
    </rule>

</urlrewrite>

私はマニュアルを注意深く読みませんでしたが、あなたのブラウザを http:// yourhost:xxxx/privateroom で更新すると、アプリが物理的に既存のビューを見つけようとする http://yourhost:xxxx/privateroom 。しかし、それはありません。そして、それをurベースページにリダイレクトすると、angularは、その状態の定義を使用して物理ファイルへの正しいリンクを構築します。理論上は間違いますが、実際には機能します

2
Sobik

サーバーを構成できない場合は、次のようにweb.xmlを構成して、ユーザーがhtml5プッシュパス上にあるときに更新を処理します。

<error-page>
    <!-- Mapping a 404 when user refreshes with an html5 Push route-->
    <error-code>404</error-code>
    <location>/index.html</location>
</error-page>
2
santon