Angular 2 Routing Does Not Work When Deployed to Http Server
I am going to develop a simple Angular 2 application. I have created a project with routing, using Angular CLI and added several components to the app using 'ng generate component ' command. Then I specified routing in the app-routing.module.ts as following.
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { HomeComponent } from './home/home.component'; import { AboutComponent } from './about/about.component'; import { UserComponent } from './user/user.component'; import { ErrorComponent } from './error/error.component'; import { SpecialpageComponent } from './specialpage/specialpage.component'; const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'about', component: AboutComponent }, { path: 'user', component: UserComponent }, { path: 'specialpage', component: SpecialpageComponent }, { path: '**', component: ErrorComponent } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], providers: [] }) export class AppRoutingModule { }
app.module.ts is as following.
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { HomeComponent } from './home/home.component'; import { AboutComponent } from './about/about.component'; import { ErrorComponent } from './error/error.component'; import { UserComponent } from './user/user.component'; import { SpecialpageComponent } from './specialpage/specialpage.component'; @NgModule({ declarations: [ AppComponent, HomeComponent, AboutComponent, ErrorComponent, UserComponent, SpecialpageComponent ], imports: [ BrowserModule, FormsModule, HttpModule, AppRoutingModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
I have not added any modifications for the other components. Then I deployed the application using 'ng serve' command and the app works fine with the links. Eg: http://localhost:4200/about
But when I deploy the project in http-server, the links do not work as expected. I deployed the app using 'http-server ./dist' command and the app gets deployed fine, but the links do not work. When I go to 'http://localhost:4200/about', it gives 404 error.
Am I doing anything wrong? Why 'ng-serve' works and 'http-server' does not work?
Any help would be appreciated. Thanks in advance.
I have uploaded my project to github.
Solution 1:
This problem is solved by implementing HashLocationStrategy
which adds #
to all your routes. You achieve this by adding HashLocationStrategy
to AppModule
providers
.
providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}],
and add the corresponding import
import { HashLocationStrategy, LocationStrategy } from '@angular/common';
This will solve your problem.
And if you don't want to use the HashLocationStrategy
, you can use the PathLocationStrategy
, and so your Angular app will not show Hash in the URL.
Solution 2:
This is because http-server does not support fallback like lite-server or web pack-dev server. This is why it shows 404 not found. There are two solution to resolve this issue:
- you can use HashLocationStrategy like mentioned above.
- If you are deploying it to Apache or IIS server then you can simply add configurations as mentioned here!
Note: For development you can use lite-server.
Hope this will help you.
Solution 3:
I've resolved this problem with adding this in AppModule Providers:
providers: [{provide: LocationStrategy, useClass: PathLocationStrategy}]
and importing
import { PathLocationStrategy, LocationStrategy } from '@angular/common';
Then I created .htaccess:
RewriteEngine On
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
# If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html
Everything works great without # in URLs :)
Solution 4:
It will be solved in this way:
Case-1: For version less than Angular 5.1
1) Use HashLocationStrategy like mentioned below: In AppModule do the following.
1.1) import { HashLocationStrategy, LocationStrategy } from '@angular/common';
1.2) providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}]
Case-2: For version equal or more than Angular 5.1
2.1) Angular has introduced this property onSameUrlNavigation for overcoming refresh issue on the server.
2.2) Add onSameUrlNavigation to the RouterModule.forRoot
in imports array .
a) In Application main routing module, i,e app.routing.module.ts / app.routing.ts add the property
See below:
@ngModule({
imports:
[
RouterModule.forRoot(routes, {onSameUrlNavigation: ‘reload’})
],
exports: [RouterModule],
});
Hope it help somebody.
Solution 5:
It will happen because it goes to find a page about which is not there inside at all hence 404. Possible options:
-
If you want to go with http-server then use a proxy which will redirect everything to http://localhost:your-port.
Option:
-P
or--proxy
Proxies all requests which can't be resolved locally to the given url. e.g.:-P http://someurl.com
-
Don't use express at all. Create your own http-server using express & Redirect everything to index.html
Assuming public is your folder where u keep all transpiled things.
var express = require('express'); var app = express(); var path = __dirname + '/public'; var port = 8080; app.use(express.static(path)); app.get('*', function(req, res) { res.sendFile(path + '/index.html'); }); app.listen(port);