I'm new to Angular 2. 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?
This question is related to
angular
angular2-routing
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).
<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
server {
server_name my-app;
root /path/to/app;
location / {
try_files $uri $uri/ /index.html;
}
}
<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>
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 {}
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 { }
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 {}
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>
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();
}
});
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}
]);
Source: Stackoverflow.com