web-dev-qa-db-ja.com

ページをリロードするとAngularJS HTML 5モードで間違ったGETリクエストが発生する

アプリのHTML 5モードを有効にしたいです。次に示すように、構成用に次のコードを追加しました。 ここ

return app.config(['$routeProvider','$locationProvider', function($routeProvider,$locationProvider) {

    $locationProvider.html5Mode(true);
    $locationProvider.hashPrefix = '!';

    $routeProvider.when('/', {
        templateUrl: '/views/index.html',
        controller: 'indexCtrl'
    });
    $routeProvider.when('/about',{
        templateUrl: '/views/about.html',
        controller: 'AboutCtrl'
    });

ご覧のとおり、私は$locationProvider.html5modeを使用し、ng-hrefを除外するように/#/にあるすべてのリンクを変更しました。

問題

現時点で、私はlocalhost:9000/に行き、インデックスページを見て、そしてlocalhost:9000/aboutのような他のページにナビゲートすることができます。

ただし、localhost:9000/aboutページを更新すると問題が発生します。次のような出力が得られます。Cannot GET /about

ネットワーク通話を見ると:

Request URL:localhost:9000/about
Request Method:GET

私が最初にlocalhost:9000/に行き、そして次に/aboutにナビゲートするボタンをクリックすると、私は得ます:

Request URL:http://localhost:9000/views/about.html

これはページを完全にレンダリングします。

更新したときにAngularを有効にして正しいページを表示するにはどうすればよいですか?

191

から 角度のドキュメント

サーバー側
このモードを使用するには、サーバー側でURLの書き換えが必要です。基本的に、すべてのリンクをアプリケーションのエントリポイントに書き換える必要があります(例:index.html)。

その理由は、あなたが最初にページ(/about)にアクセスしたとき、例えば更新後、ブラウザはこれが実際のURLではないことを知る方法がないため、先に進んでロードします。ただし、最初にルートページとすべてのjavascriptコードをロードした場合は、/about Angularに移動したときにブラウザがサーバーにアクセスして適切に処理しようとする前にそこに入ることができます

99
James Sharp

ブラウザ内のリンクがhttp://yourdomain.com/pathのようになるように設定することがいくつかあります。これらは角度のある設定+サーバー側です。

1)AngularJS

$routeProvider
  .when('/path', {
    templateUrl: 'path.html',
  });
$locationProvider
  .html5Mode(true);

2)サーバー側、ルートフォルダ内に.htaccessを置いて貼り付けてください。

RewriteEngine On 
Options FollowSymLinks

RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /#/$1 [L]

Angularjsのhtml5モードと異なる環境ごとに必要な設定について読むためのもっとおもしろいもの https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions# html5modeを使って作業するためのサーバの設定方法 この質問はあなたに役立つかもしれません $ location/html5モードとhashbangモードの切り替え/リンクの書き換え

62
lokers

私は同様の問題を抱えていたので、私はそれを解決しました:

  • インデックスページで<base href="/index.html">を使う

  • 次のように、私のノード/ Expressサーバーでキャッチオールルートミドルウェアを使用します(ルーターの後に置きます)。

app.use(function(req, res) {
    res.sendfile(__dirname + '/Public/index.html');
});

私はそれがあなたを稼働させるはずだと思います。

Apacheサーバーを使用している場合は、リンクをmod_rewriteしてください。難しいことではありません。設定ファイルを少し変更するだけです。

すべては、あなたがangularjsでhtml5modeを有効にしていると仮定しています。今すぐAngular 1.2では、ベースURLを宣言することは実際にはもう推奨されていません。

34
Taye

BrowserSyncとGulpのためのソリューション。

から https://github.com/BrowserSync/browser-sync/issues/204#issuecomment-10262364

最初にconnect-history-api-fallbackをインストールしてください。

npm --save-dev install connect-history-api-fallback

それをgulpfile.jsに追加してください。

var historyApiFallback = require('connect-history-api-fallback');

gulp.task('serve', function() {
  browserSync.init({
    server: {
      baseDir: "app",
      middleware: [ historyApiFallback() ]
    }
  });
});
26
Oscar

アプリをロードするには、すべてをindex.htmlに書き換えるようにサーバーを設定する必要があります。

https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#wiki-how-to-configure-your-server-to-work-with-html5mode

13
grant

GruntプロジェクトのURL書き換えをシミュレートするための簡単なconnectミドルウェアを書きました。 https://Gist.github.com/muratcorlu/5803655

あなたはそのように使うことができます:

module.exports = function(grunt) {
  var urlRewrite = require('grunt-connect-rewrite');

  // Project configuration.
  grunt.initConfig({
    connect: {
      server: {
        options: {
          port: 9001,
          base: 'build',
          middleware: function(connect, options) {
            // Return array of whatever middlewares you want
            return [
              // redirect all urls to index.html in build folder
              urlRewrite('build', 'index.html'),

              // Serve static files.
              connect.static(options.base),

              // Make empty directories browsable.
              connect.directory(options.base)
            ];
          }
        }
      }
    }
  })
};
10
Murat Çorlu

MVCとAngularJSを使用して.NETスタックにいる場合は、URLから「#」を削除する必要があります。

  1. _Layoutページでベースのhrefを設定します。<head> <base href="/"> </head>

  2. それから、Angular App Configに以下を追加します。$locationProvider.html5Mode(true)

  3. 上記はURLから '#'を削除しますが、ページの更新は機能しません。 "yoursite.com/about"ページにいる場合は、更新すると404が返されます。これは、MVCがアンギュラルーティングについて知らないためです。ルーティングパスこれを回避するには、すべてのMVCページ要求を単一のMVCビューに送信します。これを行うには、すべてのURLを受け取るルートを追加します。


routes.MapRoute(
        name: "App",
        url: "{*url}",
        defaults: new { controller = "Home", action = "Index" }
    );
8
Maksood

html5modeでのページ更新後の404エラーを防ぐためのIIS URL書き換え規則

WindowsでIISの下で角度ランニングの場合

<rewrite>
  <rules>
    <rule name="AngularJS" stopProcessing="true">
      <match url=".*" />
      <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
      </conditions>
      <action type="Rewrite" url="/" />
    </rule>
  </rules>
</rewrite>

NodeJS/ExpressJS html5modeでのページ更新後の404エラーを回避するための経路

Node/Express下での角度ランニング用

var express = require('express');
var path = require('path');
var router = express.Router();

// serve angular front end files from root path
router.use('/', express.static('app', { redirect: false }));

// rewrite virtual urls to angular app to enable refreshing of internal pages
router.get('*', function (req, res, next) {
    res.sendFile(path.resolve('app/index.html'));
});

module.exports = router;

詳細情報: AngularJS - NodeJSおよびIISで404エラーを発生させずにHTML5モードページの更新を有効にする

8
Jason

他の人が言ったように、サーバー上のルートを書き換えて<base href="/"/>を設定する必要があります。

gulp-connectの場合:

npm install connect-pushstate

var gulp = require('gulp'),
  connect = require('gulp-connect'),
  pushState = require('connect-pushstate/lib/pushstate').pushState;
...
connect.server({
  ...
  middleware: function (connect, options) {
    return [
      pushState()
    ];
  }
  ...
})
....
5
Brett

私は自分の開発環境でApache(xampp)を使い、本番環境でApacheを使います。

errorDocument 404 /index.html

.htaccessに私のためにこの問題を解決します。

4
crlshn

私は解決しました

test: {
        options: {
          port: 9000,
          base: [
            '.tmp',
            'test',
            '<%= yeoman.app %>'
          ],
         middleware: function (connect) {
                  return [
                      modRewrite(['^[^\\.]*$ /index.html [L]']),
                      connect.static('.tmp'),
                      connect().use(
                          '/bower_components',
                          connect.static('./bower_components')
                      ),
                      connect.static('app')
                  ];
              }
        }
      },
3
Silvio Troia

私はより大きな質問からこの質問に答えています:

$ locationProvider.html5Mode(true)を追加すると、私のサイトではURLの貼り付けが許可されません。 html5Modeがtrueのときにサーバーが動作するように設定するにはどうすればよいですか?

Html5Modeを有効にすると、#文字はURLに使用されなくなります。 #記号はサーバー側の設定を必要としないので便利です。 #がなければ、URLはずっときれいに見えますが、サーバーサイドの書き換えも必要になります。ここではいくつかの例を示します。

AngularJSを使ったExpress Rewriteの場合は、次の更新でこれを解決できます。

app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname + '/public/app/views/index.html'));
});

そして

<!-- FOR ANGULAR ROUTING -->
<base href="/">

そして

app.use('/',express.static(__dirname + '/public'));
3
Ironheartbj18

GruntとBrowsersyncのためにここでconnect-modrewrite を使用してください

var modRewrite = require('connect-modrewrite');    


browserSync: {
            dev: {
                bsFiles: {

                    src: [
                        'app/assets/css/*.css',
                        'app/*.js',
                        'app/controllers/*.js',
                        '**/*.php',
                        '*.html',
                        'app/jade/includes/*.jade',
                        'app/views/*.html',
               ],
            },
        options: {
            watchTask: true,
            debugInfo: true,
            logConnections: true,
            server: {
                baseDir :'./',
                middleware: [
                       modRewrite(['!\.html|\.js|\.jpg|\.mp4|\.mp3|\.gif|\.svg\|.css|\.png$ /index.html [L]'])
                ]
            },

            ghostMode: {
                scroll: true,
                links: true,
                forms: true
                    }
                }
            }
        },
3
MrThunder

私はあなたの問題はサーバーに関連していると思います。 HTML5モードに関する(あなたの質問のリンクにある)角度に関する文書には、次のように記載されています。

サーバーサイドこのモードを使用するには、サーバーサイドでURLの書き換えが必要です。基本的に、すべてのリンクをアプリケーションのエントリポイントに書き換える必要があります(例:index.html)。

/ aboutから/にURLの書き換えを設定する必要があると思います。

2
lucuma

Expressにサーバーリダイレクトがありました。

app.get('*', function(req, res){
    res.render('index');
});

<base href="/" />を追加した後も、ページの更新に関する問題が発生していました。

解決策:ページ内の実際のリンクを使用して移動していることを確認してください。 URLにルートを入力しないでください。ページが更新されます。 (愚かな間違い、私は知っています)

:-P

2
Cody

最後に、サーバー側でこの問題を解決する方法がありました。AngularJ自体の問題であり、1.5 Angularjsを使用していて、ページをリロードしても同じ問題が発生しました。しかし、私のserver.jsファイルに以下のコードを追加した後、それは私の一日を節約しますしかし、これは適切な解決策ではないか、または良い方法ではありません。

app.use(function(req, res, next){
  var d = res.status(404);
     if(d){
        res.sendfile('index.html');
     }
});
1
Anil Yadav

私はこれまで使ってきたこの簡単な解決策とその成果を持っています。

App/Exceptions/Handler.php

一番上にこれを追加します。

use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

それからrenderメソッドの中に

public function render($request, Exception $exception)
{
    .......

       if ($exception instanceof NotFoundHttpException){

        $segment = $request->segments();

        //eg. http://site.dev/member/profile
        //module => member
        // view => member.index
        //where member.index is the root of your angular app could be anything :)
        if(head($segment) != 'api' && $module = $segment[0]){
            return response(view("$module.index"), 404);
        }

        return response()->fail('not_found', $exception->getCode());

    }
    .......

     return parent::render($request, $exception);
}
0
Digitlimit

JHipsterで生成されたJava +角度付きアプリでも同じ問題がありました。私はそれをプロパティとフィルタのすべての角度ページのリストで解決しました:

application.yml:

angular-pages:
  - login
  - settings
...

AngularPageReloadFilter.Java

public class AngularPageReloadFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.getRequestDispatcher("index.html").forward(request, response);
    }
}

WebConfigurer.Java

private void initAngularNonRootRedirectFilter(ServletContext servletContext,
                                              EnumSet<DispatcherType> disps) {
    log.debug("Registering angular page reload Filter");
    FilterRegistration.Dynamic angularRedirectFilter =
            servletContext.addFilter("angularPageReloadFilter",
                    new AngularPageReloadFilter());
    int index = 0;
    while (env.getProperty("angular-pages[" + index + "]") != null) {
        angularRedirectFilter.addMappingForUrlPatterns(disps, true, "/" + env.getProperty("angular-pages[" + index + "]"));
        index++;
    }
    angularRedirectFilter.setAsyncSupported(true);
}

誰かに役立つことを願っています。

0
Igor Zboichik

Gulp + browserSync:

Npmでconnect-history-api-fallbackをインストールし、後であなたのサーブグループタスクを設定してください。

var historyApiFallback = require('connect-history-api-fallback');

gulp.task('serve', function() {
  browserSync.init({
    proxy: {
            target: 'localhost:' + port,
            middleware: [ historyApiFallback() ]
        }
  });
});
0
Oscar Caicedo

同じディレクトリにindex.htmlとGruntfile.jsがある場合はうまくいきます。

https://npmjs.org/package/grunt-connect-pushstate

それからあなたのGruntfileに:

 var pushState = require('grunt-connect-pushstate/lib/utils').pushState;


    connect: {
    server: {
      options: {
        port: 1337,
        base: '',
        logger: 'dev',
        hostname: '*',
        open: true,
        middleware: function (connect, options) {
          return [
            // Rewrite requests to root so they may be handled by router
            pushState(),
            // Serve static files
            connect.static(options.base)
          ];
        }
      },
    }
},
0
Michał Lach
I solved same problem using modRewrite.  
AngularJS is reload page when after # changes.  
But HTML5 mode remove # and invalid the reload.  
So we should reload manually.
# install connect-modrewrite
    $ Sudo npm install connect-modrewrite --save

# gulp/build.js
    'use strict';
    var gulp = require('gulp');
    var paths = gulp.paths;
    var util = require('util');
    var browserSync = require('browser-sync');
    var modRewrite  = require('connect-modrewrite');
    function browserSyncInit(baseDir, files, browser) {
        browser = browser === undefined ? 'default' : browser;
        var routes = null;
        if(baseDir === paths.src || (util.isArray(baseDir) && baseDir.indexOf(paths.src) !== -1)) {
            routes = {
                '/bower_components': 'bower_components'
            };
        }

        browserSync.instance = browserSync.init(files, {
            startPath: '/',
            server: {
            baseDir: baseDir,
            middleware: [
                modRewrite([
                    '!\\.\\w+$ /index.html [L]'
                ])
            ],
            routes: routes
            },
            browser: browser
        });
    }
0
keiwt

サーバー側のコードはJavaです。以下の手順に従ってください。

ステップ1:urlrewritefilter JARをダウンロードする ここをクリック そしてビルドパスWEB-INF/libに保存する

ステップ2:HTML5モードを有効にする$ locationProvider.html5Mode(true);

ステップ3:ベースURLを設定する<base href="/example.com/"/>

ステップ4:コピーしてあなたのWEB.XMLに貼り付け

 <filter>
     <filter-name>UrlRewriteFilter</filter-name>
 <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

ステップ5:WEN-INF/urlrewrite.xmlにファイルを作成する

 <urlrewrite default-match-type="wildcard">


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

    <!--Write every state dependent on your project url-->
    <rule>
            <from>/example</from>
            <to>/index.html</to>
        </rule>
    </urlrewrite>
0
senthil raja

以下のコードスニペットをnode.jsファイルに追加することで問題を解決しました。

app.get("/*", function (request, response) {
    console.log('Unknown API called');
    response.redirect('/#' + request.url);
});

注:ページを更新すると、Angular pageではなくAPIが検索されます(URLに#タグがないため)。上記のコードを使用して、#を使用してURLにリダイレクトします。

0
Ram Gollapalli