简体   繁体   中英

Angular App on Apache Server without rewrite rules

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM