web-dev-qa-db-ja.com

Angular 2:404エラーがブラウザを介して更新するときに発生します

私はAngular 2に慣れていません。2.私のシングルページアプリケーションを "myapp"という名前のフォルダ内のサーバーに保存しました。ベースのURLを http://example.com/myapp/ `に変更しました。

私のプロジェクトは2ページあります。それで私はAngular 2ルーティングを実装します。デフォルトのページをログインとして設定しました。ブラウザにhttp://example.com/myapp/と入力すると、自動的にhttp://example.com/myapp/loginにリダイレクトされます。しかし、そのページを更新すると、404が見つからないというhttp://example.com/myapp/loginエラーが発生します。

しかし、ライトサーバーを使ってプロジェクトを実行すれば、すべてうまくいきます。この場合、index.htmlのURLは"/"になります。どのように修正しますか?

142
DAN

実際には、ブラウザ内の実際のアドレスが更新されているため(そして#/ hashbangアプローチなしで)、アプリケーションの更新時に404エラーが発生するのが普通です。デフォルトでは、HTML 5の履歴はAngular 2での再利用に使用されます。

404エラーを修正するには、定義した各ルートパスにindex.htmlファイルを提供するようにサーバーを更新する必要があります。

HashBangアプローチに切り替えたい場合は、この設定を使用する必要があります。

import {bootstrap} from 'angular2/platform/browser';
import {provide} from 'angular2/core';
import {ROUTER_PROVIDERS} from 'angular2/router';
import {LocationStrategy, HashLocationStrategy} from '@angular/common';

import {MyApp} from './myapp';

bootstrap(MyApp, [
  ROUTER_PROVIDERS,
  {provide: LocationStrategy, useClass: HashLocationStrategy}
]);

この場合、ページを更新すると、ページが再び表示されます(ただし、アドレスに#が表示されます)。

Webサイトを更新すると404が表示されます。これはAngular 2とfirebaseの場合です

それがあなたに役立つことを願っています、ティエリー

109

Angular 2 final versionに更新

App.module.tsで:

  • インポートを追加します。

    import { HashLocationStrategy, LocationStrategy } from '@angular/common';
    
  • そしてNgModuleプロバイダで、以下を追加してください。

    {provide: LocationStrategy, useClass: HashLocationStrategy}
    

(app.module.ts):

import { NgModule }       from '@angular/core';
import { BrowserModule  } from '@angular/platform-browser';
import { AppComponent }   from './app.component';
import { HashLocationStrategy, LocationStrategy } from '@angular/common';

@NgModule({
    declarations: [AppComponent],
    imports: [BrowserModule],
    providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}],
    bootstrap: [AppComponent],
})
export class AppModule {}

代替案

{useHash:true}引数を指定してRouterModule.forRootを使用します。

例:(from 角度ドキュメント

import { NgModule } from '@angular/core';
...

const routes: Routes = [//routes in here];

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    RouterModule.forRoot(routes, { useHash: true })
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }
212
Asaf Hananel

PathLocationStrategyではなくHashLocationStrategy(つまりhtml5Mode)を本当に必要とする(私のような)人のためには、どうやってHTML5MODEを使うようにサーバーを設定するを見てください。

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

ここでは、Wikiが紛失した場合に備えて、Wikiから3つの例をコピーするだけです。他の例は、キーワード "URL rewrite"を検索することで見つけることができます(例:Firebaseの場合は この回答 )。

アパッチ

<VirtualHost *:80>
    ServerName my-app

    DocumentRoot /path/to/app

    <Directory /path/to/app>
        RewriteEngine on

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

        # Rewrite everything else to index.html to allow HTML5 state links
        RewriteRule ^ index.html [L]
    </Directory>
</VirtualHost>

書き換えモジュールのドキュメント

nginx

server {
    server_name my-app;

    root /path/to/app;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

try_filesのドキュメント

IIS

<system.webServer>
  <rewrite>
    <rules> 
      <rule name="Main Rule" 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>
</system.webServer>
86
Franklin Yu

私は同じ問題を抱えていました。私のAngularアプリケーションは、Windowsサーバー上で実行されています。

私は root ディレクトリに web.config ファイルを作ることでこの問題を解決しました。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <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>
  </system.webServer>
</configuration>
23
Bennie-be

おそらくあなたのルートをRouterModuleに登録しながらそれを行うことができます。次のように、プロパティ "useHash:true"を持つ2番目のオブジェクトを渡すことができます。

import { NgModule }       from '@angular/core';
import { BrowserModule  } from '@angular/platform-browser';
import { AppComponent }   from './app.component';
import { ROUTES }   from './app.routes';

@NgModule({
    declarations: [AppComponent],
    imports: [BrowserModule],
    RouterModule.forRoot(ROUTES ,{ useHash: true }),],
    providers: [],
    bootstrap: [AppComponent],
})
export class AppModule {}
16
Niyaz

Angular 2 rc4以降を使用している、これを読んでいる人にとって、LocationStrategyはルーターから共通に移動したようです。そこからインポートする必要があります。

また、「提供」行を囲む中括弧にも注意してください。

main.ts

// Imports for loading & configuring the in-memory web api
import { XHRBackend } from '@angular/http';

// The usual bootstrapping imports
import { bootstrap }      from '@angular/platform-browser-dynamic';
import { HTTP_PROVIDERS } from '@angular/http';

import { AppComponent }         from './app.component';
import { APP_ROUTER_PROVIDERS } from './app.routes';
import { Location, LocationStrategy, HashLocationStrategy} from '@angular/common';

bootstrap(AppComponent, [
    APP_ROUTER_PROVIDERS,
    HTTP_PROVIDERS,
    {provide: LocationStrategy, useClass: HashLocationStrategy}
]);
5
Koen De Couck

Visual Studio 2015でASP.NET Core 1を介してAngular 2を実行している場合は、JürgenGutschのこのソリューションが役に立ちます。彼はそれを ブログ投稿 で説明しています。それは私にとって最良の解決策でした。下記のC#コードをapp.UseStaticFiles()の直前にあるStartup.csのpublic void Configure()に配置します。

app.Use( async ( context, next ) => {
    await next();

    if( context.Response.StatusCode == 404 && !Path.HasExtension( context.Request.Path.Value ) ) {
        context.Request.Path = "/index.html";
        await next();
    }
});
5