By default, Angular does not return an error 404 when you surf to a page that doesn’t exist. This is a significant drawback since pages that don’t exist and don’t return an error 404 can be indexed and stored in the cache of the search engine.
Although we can not eliminate this problem with the built-in Angular tools, this is possible thanks to the Universal tool. For the convenience of perception, the process is divided into 4 simple steps:
- creating a special component to show 404 page;
- setting a redirection to this page to show it each time 404 error occurs;
- connecting the Universal tool;
- making the component sending 404 server code.
So, let’s get started!
1. Create a new component for 404 page
First, you need to create a component to show the page, which will be displayed when error 404 occurs. To do this, it is sufficient to generate a new component through the Angular CLI using the command:
ng generate component not-found
2. Set a redirect to the 404 page
After that, you need to define a new ‘Not Found’ component as a separate route and specify that when you surf to a page that doesn’t exist, you need to redirect to the ‘Not Found’ page. As a result, your object with routes should look similar to this:
export const appRoutes: Routes = [
// Other routes here...
{
path: '404', component: NotFoundComponent
},
{
path: '**', redirectTo: '/404'
}
];
We’ve just created a redirect to the ‘Not Found’ page, but our site still gives the status of 200. To restore the status of 404 we will use Universal.
3. Connect Universal
First, you need to go to the file with the server (usually this file is called ‘server.ts’) and import the necessary modules:
import { ngExpressEngine } from '@nguniversal/express-engine';
import { renderModuleFactory } from '@angular/platform-server';
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
import { REQUEST, RESPONSE } from '@nguniversal/express-engine';
import { ValueProvider } from '@angular/core';
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main.bundle');
Note that when importing the ‘AppServerModuleNgFactory’ and ‘LAZY_MODULE_MAP’ modules we need to specify the location of the server file main.bundle.js, the location of this file may be different in your project.
Next, we need to connect ‘@ nguniversal / express-engine’ in order to process the information from the component. To do this we need to insert the following piece of code into the server file:
app.engine('html', (_, options, callback) = > {
const opts = {
document: template,
url: options.req.url,
extraProviders: [
provideModuleMap(LAZY_MODULE_MAP),
{
provide: REQUEST,
useValue: options.req
},
{
provide: RESPONSE,
useValue: options.req.res,
},
]
};
renderModuleFactory(AppServerModuleNgFactory, opts)
.then(html = > callback(null, html)
);
});
Note: if you already have a call to `app.engine`, then you need to replace it with the code above.
4. Make the component sending 404 status
The final step is sending status 404 from the component. To do this, go to the ‘Not Found’ component and import `@ nguniversal / express-engine`:
import { RESPONSE } from '@nguniversal/express-engine';
Then we implement `RESPONSE` as a dependency:
constructor( @Optional() @Inject(RESPONSE) private response: any ) { }
After that, you can already send the status of 404. You can also specify a message to send the status, in the end, your component should look like this:
import {Component, Inject, OnInit, Optional} from '@angular/core';
import {RESPONSE} from '@nguniversal/express-engine';
@Component({
selector: 'app-not-found',
templateUrl: './not-found.component.html',
styleUrls: ['./not-found.component.sass']
})
export class NotFoundComponent implements OnInit {
constructor(
@Optional() @Inject(RESPONSE) private response: any
) {}
ngOnInit() {
this.response.statusCode = 404;
this.response.statusMessage = '404 - Page Not Found';
}
}
Everything is ready, now when we surf to a page that doesn’t exist on your Angular application, we get the status 404.
Have any questions left? Feel free to contact us!