13

i would like to deploy my app in Angular to production server but I have problems. App works corectly when I use only angular routing (change component, not redirecting) but when I refresh the page in browser, I get a 404 page returned from IIS (I use IIS as the web server)

Here is my angular routing:

const appRoutes: Routes = [
    { path: '', redirectTo: '/home', pathMatch: 'full', canActivate: [AuthGuard] },
    { path: 'home', component: DashboardComponent, canActivate: [AuthGuard] },
    { path: "profile", component: UserProfileComponent, canActivate: [AuthGuard] },
    { path: '400', component: ErrorComponent },
    { path: '401', component: ErrorComponent },
    { path: '403', component: ErrorComponent },
    { path: '404', component: ErrorComponent },
    { path: '500', component: ErrorComponent },
    { path: '503', component: ErrorComponent },
    { path: '**', redirectTo: '/404' }
]
Graham
  • 7,431
  • 18
  • 59
  • 84
bluray
  • 1,875
  • 5
  • 36
  • 68
  • you are implemented `[AuthGuard]` to some of your routes, so you must have to use `providers` in `app.routing` file like this `providers: [AuthGuard, LoginService]` to register `services` which you use for `[AuthGuard]` . Did you do that? – nivas Jul 13 '17 at 05:52
  • Routes are defined in routing.module.ts which use in app.module where is provider AuthGuard. Must be provider in routing.module or only in app.module? – bluray Jul 13 '17 at 05:54
  • you have to declare it in `routing.module.ts` with @NgModule decorator – nivas Jul 13 '17 at 05:55
  • Is the 404 coming from Angular or IIS? – Graham Jul 13 '17 at 05:58
  • 404 coming from IIS – bluray Jul 13 '17 at 05:59
  • We had a similar issue in node, we had to redirect these requests to our /dist/index.html file. Hopefully someone who has seen this in IIS can give you the code, chances are it's a setting in your web.config. – Graham Jul 13 '17 at 06:09
  • Possible duplicate of [Angular2 not loading when directly browsed to route address or on refresh](https://stackoverflow.com/questions/41351052/angular2-not-loading-when-directly-browsed-to-route-address-or-on-refresh) – Graham Jul 13 '17 at 06:11
  • Can you show example of web.config or tell me what i must have in web.config. i havent web.config in my app – bluray Jul 13 '17 at 06:11
  • Please take a look at the link above, you are definitely encountering the same issue as what that person saw. – Graham Jul 13 '17 at 06:14
  • Yes, he has the same problem. But i must havebase href="./" when i have only / app not load. – bluray Jul 13 '17 at 06:15

7 Answers7

21

This work for angular 8, add .htaccess to your project file

<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
    Options -MultiViews -Indexes
</IfModule>

RewriteEngine On

# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]

# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.html [L]

Segun Adeniji
  • 370
  • 5
  • 11
12

If you are using angular 6,7 this method works (If you are okay with /#/ in your URL.

In app.module.ts

import {LocationStrategy, HashLocationStrategy} from '@angular/common';

After import add following line to providers.

{provide: LocationStrategy, useClass: HashLocationStrategy}

ex:

providers: [AuthService, 
            AuthGuard, 
            FlxUiDataTable,
            {provide: LocationStrategy, useClass: HashLocationStrategy}]

This will solve your issue. Read Documentation here.

Nimezzz
  • 1,814
  • 14
  • 15
9

I modified the web.config in my app:

<configuration>
  <system.webServer>
<rewrite>
    <rules>
        <rule name="redirect all" stopProcessing="true">
            <match url="^(.*)$" ignoreCase="false" />
            <conditions logicalGrouping="MatchAll">
                <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" pattern="" ignoreCase="false" />
            </conditions>
            <action type="Rewrite" url="./" appendQueryString="true" />
        </rule>
    </rules>
</rewrite>
  </system.webServer>
</configuration>

In index.html is <base href="./">. Refreshing the page is now ok.

Graham
  • 7,431
  • 18
  • 59
  • 84
bluray
  • 1,875
  • 5
  • 36
  • 68
7

This will work on following servers.

Apache Server

Add .htaccess on root to your project

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.html [L]
</IfModule>

IIS Server

Add web.config

<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Imported Rule 1" stopProcessing="true">
          <match url="^(.*)/$" ignoreCase="false" />
          <conditions>
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
          </conditions>
          <action type="Redirect" redirectType="Permanent" url="/{R:1}" />
        </rule>
        <rule name="Imported Rule 2" stopProcessing="true">
          <match url="^" ignoreCase="false" />
          <conditions>
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
          </conditions>
          <action type="Rewrite" url="index.html" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

Nginx Server

make changes on server file Instead of using: try_files $uri $uri/ =404;

try using: try_files $uri $uri/ /index.html;

        server {
                listen 80;
                listen [::]:80;
        
                root /var/www/example.com/html;
        
            index index.html index.htm index.nginx-debian.html;
        
                server_name example.com www.example.com;
        
                location / {
                    try_files $uri $uri/ /index.html;
                 }
        }
Parth Developer
  • 1,371
  • 1
  • 13
  • 30
Shaan Ansari
  • 510
  • 6
  • 10
1

My initial workaround was to just redirect on 404 back to root, and so far, I don't see a down-side to this. To my surprise, both the request path and parameters persist when refreshing. This is in an IIS 10 environment with Angular 9, and a Chrome-only (internal app) so there may be other factors at play that I'm unaware of that are only making this seem sustainable. Will try to remember to come back to my answer should we discover something.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpErrors>
            <remove statusCode="404" subStatusCode="-1" />
            <error statusCode="404" prefixLanguageFilePath="" path="/" responseMode="ExecuteURL" />
        </httpErrors>
    </system.webServer>
</configuration>
storsoc
  • 309
  • 1
  • 7
0

This worked for me:

  1. Add web.config to /src

     <configuration>
     <system.webServer>
         <rewrite>
             <rules>
                 <rule name="redirect all" stopProcessing="true">
                     <match url="^(.*)$" ignoreCase="false" />
                     <conditions logicalGrouping="MatchAll">
                         <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" pattern="" ignoreCase="false" />
                     </conditions>
                     <action type="Rewrite" url="./" appendQueryString="true" />
                 </rule>
             </rules>
         </rewrite>
     </system.webServer></configuration>
    
  2. On angular.json, on asset add

    "src/web.config"

mpalencia
  • 5,481
  • 4
  • 45
  • 59
0

I fix this bug by adding { useHash: true } to RouterModule.forRoot() in the app.module.ts or app-routing.module.ts. For example:

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    RouterModule.forRoot(routes, { useHash: true })  // .../#/crisis-center/
  ],
  declarations: [
    AppComponent,
    PageNotFoundComponent
  ],
  providers: [

  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }
Linh Dao
  • 1,305
  • 1
  • 19
  • 31