245

I have stored my single-page application in my server within a folder named as "myapp". I have changed the URL in the base to http://example.com/myapp/`.

My project has two pages. So I implement Angular 2 routing. I set the default page as login. When I type http://example.com/myapp/ in my browser it will redirect automatically to http://example.com/myapp/login. But if refresh that page I get a 404 error, saying that http://example.com/myapp/login is not found.

But if I run my project using the lite server everything is working. In this case the base URL in index.html will be "/". How do fix it?

3
  • Currently, I worked with the angular 9 application and deployed it on an IIS server with a web.config file and when we refresh the page it loads the angular app correctly. I think this is not an issue with the angular application. But when I deployed the code to the Ubuntu server application gives the 404 not found error because we did not configure the URL rewrite rules. After adding the.htaccess file for rewrite the URL's It works on refresh. Commented Oct 16, 2020 at 12:30
  • I had the same problem in production, in development was fine. This answer fixed this: stackoverflow.com/a/39103122/12603542, with useHash: true, Ill have to just figure out how to get rid of /#/ Commented Jun 2, 2021 at 9:47
  • In my case SEO folks don't want # to be there in URL, for IIS without hash it works by creating a web.config but anyone have any idea how to fix this in apache without hash location strategy? Commented Oct 8, 2023 at 6:50

7 Answers 7

296

Update for Angular 2 final version

In app.module.ts:

  • Add imports:

     import { HashLocationStrategy, LocationStrategy } from '@angular/common'; 
  • And in NgModule provider, add:

     {provide: LocationStrategy, useClass: HashLocationStrategy} 

Example (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 {} 

Alternative

Use RouterModule.forRoot with the {useHash: true} argument.

Example:(from angular docs)

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 { } 
Sign up to request clarification or add additional context in comments.

18 Comments

Answers may be rearranged according to popularity, so relative positioning will not be preserved. Please provide a link to the other answer in your answer.
This does work for me. Thank you. But is there a way to lose the #?
Yes this works for me too. But I am using auth0 for authentication and I have to provide allowed urls. when I refresh page which adds a hash now, then login it wont accept the url. What is a suggestion to fix this or remove the hashtags when the page is refreshed?
Adding providers first solution of this answer(providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}], bootstrap: [AppComponent],) DID WORK!! thanks a TON! /\!
There is a way to not use the hash (#) in the link?? The solution worked fine but now i have a link like: "test/app/#/login"
|
190

For people (like me) who really want PathLocationStrategy (i.e. html5Mode) instead of HashLocationStrategy, see How to: Configure your server to work with html5Mode from a third-party wiki:

When you have html5Mode enabled, the # character will no longer be used in your URLs. The # symbol is useful because it requires no server side configuration. Without #, the URL looks much nicer, but it also requires server side rewrites.

Here I only copy three examples from the wiki, in case the Wiki get lost. Other examples can be found by searching keyword "URL rewrite" (e.g. this answer for Firebase).

Apache (file name should be .htaccess in root directory )

<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> 

Documentation for rewrite module

nginx

server { server_name my-app; root /path/to/app; location / { try_files $uri $uri/ /index.html; } } 

Documentation for try_files

IIS (file name should be web.config in root directory )

<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> 

16 Comments

This topic relates to Angular 2(4) - your response is AngularJS related
@Playnox Everything mentioned here also applies to Angular 2 to 4. (Actually I didn't begin using Angular since 2.) You may have jumped to the conclusion by the link to Angular-UI wiki, where code sample is AngularJS.
And I get downvoted because of the false accusation. Well, at least there is some feedback...
@FranklinYu Have you seen any configurations for WebLogic servers? Haven't had any luck.
This answer in my view is the correct one, it preserves the HTML5 features of angular and makes the server function correctly.
|
156

In fact, it's normal that you have a 404 error when refreshing your application since the actual address within the browser is updating (and without # / hashbang approach). By default, HTML5 history is used for reusing in Angular2.

To fix the 404 error, you need to update your server to serve the index.html file for each route path you defined.

If you want to switch to the HashBang approach, you need to use this configuration:

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} ]); 

In this case, when you refresh the page, it will be displayed again (but you will have a # in your address).

This link could help you as well: When I refresh my website I get a 404. This is with Angular2 and firebase.

Hope it helps you, Thierry

11 Comments

This solved my problem, thanks a lot. However, is there any disadvantage in using the HashBang approach?, I mean in terms of SEO or anything else?
What if we don't want to use HashLocationStrategy but PathLocationStrategy?
@Ben As Thierry mentioned, "if you want not having a 404 error, you need to update your server to serve the index.html file for each route path you defined." Detailed ways for each server software are in Angular Wiki about working with html5Mode, or refer to the linke provided by Thierry for Firebase configuration.
answer below is for update for angular2 final version
Franklin Yu's answer should actually be the accepted answer. Thierry Templier's answer just says put back the # to get rid of the problem, which isn't an answer or use the link provided with assumes the poster is using firebase, which the poster probably is not. The wiki provided by Franklin answers the questions, with a side note, for Apache, you can add the same config in an .htaccess file.
|
39

I had the same problem. My Angular application is running on a Windows server.

I solved this problem by making a web.config file in the root directory.

<?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> 

2 Comments

@DaneVinson The Angular Wiki is even earlier. Anyway he should probably give someone credit.
In case of WebApi service (For the Server). Notice, that the angular application not placed in the same folder of WebApi. You can create another folder, and change the href in index.html
32

Perhaps you can do it while registering your root with RouterModule. You can pass a second object with property useHash:true like the below:

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 {} 

2 Comments

This is the simplest approach if you just want to get something working quickly. However, anuglar.io recommends against it "Stick with the default unless you have a compelling reason to resort to hash routes." angular.io/docs/ts/latest/guide/router.html
just adding { useHash: true } solved my problem thanks !
8

For people reading this that use Angular 2 rc4 or later, it appears LocationStrategy has been moved from router to common. You'll have to import it from there.

Also note the curly brackets around the 'provide' line.

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} ]); 

Comments

7

If you're running Angular 2 through ASP.NET Core 1 in Visual Studio 2015, you might find this solution from Jürgen Gutsch helpful. He describes it in a blog post. It was the best solution for me. Place the C# code provided below in your Startup.cs public void Configure() just before app.UseStaticFiles();

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(); } }); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.