I need to deliver an Angular application to an external team. When they try to load directly a page they get a 404 Not found error. The server is an Apache and I haven't access to this server.
I have asked them that they should configure the server according to documentation (rewrite rules): https://angular.io/guide/deployment#server-configuration but they refuse to do it. I have no other choice. I need to run the Angular application anyway or redo the application completely using directly html and js.
I need a mechanism that loads always index.html and redirects to the destination page.
This is the build command:
ng build --prod --base-href=./
I've also tried attaching the rewrite rules in a .htaccess in the same folder than my index.html but it doesn't work for them either, maybe because they haven't enabled mod_rewrite:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
The other choice when you not available to setup rewrite rules on the server (specially when you are hosting the app in a third part host), is to use a old resource in Angular. Add {useHash: true}
parameter in forRoot
method:
@NgModule({
imports: [ RouterModule.forRoot(routes, {useHash: true}) ],
exports: [ RouterModule ]
})
Automatically, any url pointed to http://yoururl.com/products , for example, will be rewrite to http://yoururl.com/#/products . You will just need to review for your menu and links to point to #/products , instead of /products .
I don't like the solution I found, but it is the only one I have achieved. It is cumbersome, makes maintenance difficult and should not be used in large applications. In my case, maintenance is not a problem and the application will practically not grow in the future.
Ideally, the server should be configured with rewrite rules to avoid all this extra code.
First : all the urls must load index.html. For this I've created an static file like onepage.html
, otherpage.html
, and so on. If I have deeper paths I need to create folders like users\\userspage.html
. The structure of my folders would look like this:
\src
\index.html
\onepage.html
\otherpage.html
\users
\userspage.html
...
Then I've edited this files to redirect to index.html from its folder. For onepage.html
, otherpage.html
:
<!doctype html>
<html></html>
<script>
window.location.href = './index.html';
</script>
For users\\userspage.html
I need to rise one level:
window.location.href = '../index.html';
Second : I need a component ( MenuComponent
) to be loaded when there is no match. For this I configure my app-routing.module.ts file in this way:
const routes: Routes = [
{ path: 'onepage.html', component: OneComponent },
{ path: 'otherpage.html', component: OtherComponent },
{ path: 'users/userspage.html', component: UsersComponent },
// ...
{ path: '**', component: MenuComponent }
];
Third : I've added to MenuComponent.html
all my urls as routerLinks:
<a id="onepage" routerLink="/onepage.html" [queryParams]="oneParams"></a>
<a id="otherpage" routerLink="/otherpage.html" [queryParams]="otherParams"></a>
...
<a id="users-userspage" routerLink="/users/usersPage.html" [queryParams]="usersParams"></a>
And my MenuComponent.ts
forward the document.referrer
params using propertys and force the click event using the routeLink of the page requested:
oneParameters = {
size: '',
color: '',
// ...
}
// other properties ...
ngOnInit() {
const paramString = document.referrer.substring(document.referrer.indexOf('?') + 1);
const pairs = paramString.split('&');
// fill properties with params ...
}
ngAfterViewInit() {
this.loadScript();
}
loadScript() {
if (document.referrer.includes('/onepage.html')) {
let el = (document.getElementById("onepage") as HTMLAnchorElement);
el.click();
}
else if (document.referrer.includes('/otherpage.html')) {
let el = (document.getElementById("otherpage") as HTMLAnchorElement);
el.click();
}
else if (document.referrer.includes('/users/userspage.html')) {
let el = (document.getElementById("users-userspage") as HTMLAnchorElement);
el.click();
}
// ...
}
I am quite new to Angular and I am sure that it can be done better, especially the mapping of parameters to the properties. I hope nobody is forced to use this method.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.