# Day?? 【牙起來】 - Angular 網頁部署設定 ## Redirect Http to Https 使用Angular重新導向 以往需要透過伺服器IIS來做額外設定、或是Apache額外設定`.htaccess`檔案 省略了這些設定的功夫,這邊直接寫在程式裡,用js的方法把重新導向的邏輯做掉了 修改`app.component.ts` ```typescript= import { Component, OnInit } from '@angular/core'; import { environment } from '../environments/environment'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], }) export class AppComponent implements OnInit { title = 'website'; ngOnInit() { if (location.protocol === 'http:') { if (environment.production) { window.location.href = location.href.replace('http', 'https'); } } } } ``` 其中必須做**是否為production環境**的判斷,否則在本地端 `ng serve` 時,預設網址是`http://localhost:4200/` 會一直導到https導致無法測試 這樣就可以都會導向到https囉 ## 部署到伺服器上 Reload 404 問題 ### 原理: `ng build`之後,只會有這些檔案被部署上伺服器 ![](https://i.imgur.com/2fxDJFg.png) 瀏覽、加載SPA網頁首頁的時候沒問題,是因為伺服器有看到`index.html`,接著由Angular透過JS來掌管一切邏輯,按下其他頁面的按鈕時,透過Router導到其他網址`page2.html`,所有作動都是在Angular內部這包檔案中運作。 但當Refresh、Reload網頁重新載入的時候,伺服器沒有看到名為`page2.html`的檔案。 所以直接返回404,根本進入不到Angular掌管的那一步。 ### 方法1 - 在伺服器端寫配置(不屬於Angular的部分) 從伺服器端出現的問題,由伺服器端寫邏輯導頁 網址維持`https://domain.com/page2.html` 又稱**Html5Mode**、**PathLocationStrategy** ### 方法2 - 在Angular加上useHash 又稱**HashMode**、**HashLocationStrategy** > 名詞解釋 > Hash: `#` > Hashbang: `#!`,AngularJS採用的模式 這個方法又有兩種做法 * 第一種做法:在`app-routing.module.ts`中加入`{useHash: true}` ```typescript= @NgModule({ imports: [RouterModule.forRoot(routes, {useHash: true})], exports: [RouterModule] }) ``` ![](https://i.imgur.com/VFcHsDE.png) * 第二種做法比較麻煩:用到了`provide`及`useClass`來覆寫 在`app.module.ts`中加入`providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}],`, ![](https://i.imgur.com/VWy7jxb.png) Hashtag就是Fragment網址段落分段 ![](https://i.imgur.com/Nk1LgEQ.png) 缺點:網址會變成`https://domain.com/#/page2.html` 變醜變的奇怪 並且無法再使用`#`Fragment來跳到指定id位置 原理:雖然網址是`https://domain.com/#/page2.html`,但瀏覽器只會發送 `https://domain.com/`,使伺服器能依循到`index.html`檔案,對應到那包Angular檔案、而非找不到返回404,接下來的事情由Angular掌管。 ```typescript= 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 {} ``` https://stackoverflow.com/questions/35284988/angular-2-404-error-occur-when-i-refresh-through-the-browser https://nicolas.riousset.com/category/software-methodologies/fixing-angular-404-page-not-found-error-on-page-refresh/ ### 方法3 - SSR prerender TODO Angular Universal https://medium.com/@dao.houssene/angular-the-hash-trap-b2d415c2c241 https://fullstackladder.dev/blog/2021/10/16/static-site-generator-using-angular-universal-prerender/ 用了之後nodejs location undefined https://stackoverflow.com/questions/70931014/location-is-not-defined-asp-net-zero-angular-universal --- Angular 17以後則是在`app.config.ts`中加入以下 ``` providers: [ provideRouter(routes, withHashLocation()), ], ```