📝

AngularでビルドしたWEBアプリをnginxにデプロイすると リロードしたときにNot Foundになるやつの対策

2021/08/17に公開約2,300字

事象

ng serveで起動した開発サーバーは特定のページで再読み込みをすると正常に表示されるのに、
ng buildでビルドしたアプリをnginxでデプロイするとNot Foundになってしまう。

環境

ミドルウェア名 バージョン
angular 12.0.3
angular-cli 12.0.3
nginx 1.21.1

結論

対策

1. HashLocationStrategyを使用する



app-routing.module.tsで{ useHash: true }を記述する。

  
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { TopComponent } from './top/top.component';
import { LoginComponent } from './login/login.component';

const routes: Routes = [
  {
    path: '',
    component: TopComponent
  },
  {
    path: 'login',
    component: LoginComponent,
  },
];
@NgModule({
  imports: [ RouterModule.forRoot(routes, { useHash: true }) ],//ここ!
  exports: [ RouterModule ],
})
export class AppRoutingModule {}

こうすることによって
https://contoso.com/signin
というURLだった場合、
http://contoso.com/#/signin
となる。

間に#が入っているとURLっぽいけど実は常にルートを見に行っているらしい。


2. nginxのdefault.confを変更する

nginxのtry_filesディレクティブを使用する。

server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html; #これを追加!
    }

この一文は

  1. URLのパス($uri)にファイルがあれば返す
  2. 1がない場合、URLのパス($uri/)にディレクトリがあれば返す
  3. 2.がない場合、ルートのindex.htmlを返す

という設定になってる。

default.confを変更したらnginx reloadで設定再読み込みで反映されるはず


どっちを採用する?

開発の初期からであればどっちを採用しても問題ないが、開発途中での変更の場合はデメリットがある。
まあでもnginxの設定変更ならほぼダメージ無いのでこっちがいいかな。

デメリット
HashLocationStrategy URLが変更になる
nginx設定変更 nginxの設定変更が必要

事象が起きる原因

AngularはSPA(Single Page Application)であり、ページ遷移の際にURLが変わっているが、
実は一つのページ内で描画するコンポーネントを変えている。
これはHTML5のHistory APIという機能を使って実現しているらしい。
(ってことはこの機能を使ってるフレームワークはこの現象が起こりうるのかな?)
なので、ng buildでビルドされたファイルを見るとhtmlファイルがindex.html一つしかない。
ルートにしかindex.htmlがないんだからそりゃNot Foundになってしまう。


なんでng serveだとNot Foundにならないの?

ng serveで起動した開発サーバーはNot Foundエラー(404)が発生した場合、index.htmlを返してくれるようになっているそうです。
それはそれで便利なんだろうけど、ずっとng serveで開発してきてビルドしたらNot Foundになるから最初に遭遇したときは焦る。。

参考

https://christina04.hatenablog.com/entry/2017/02/10/004253
https://qiita.com/tomy0610/items/77d9e10348577f321eec
GitHubで編集を提案

Discussion

ログインするとコメントできます