Table of Contents
What is Pre-rendering in angular?
Why should we pre-render Angular applications?
What is Pre-rendering in angular?
Pre-rendering creates a static page when we build an angular application. As a result, the website will load faster and will be SEO-friendly without the need for server-side rendering. The pre-rendering is helpful if we want to serve static pages in the application.
Why should we pre-render Angular applications?
Most of the obstacles that one faces with an Angular application are fixed by following the optimization techniques. Although there are still a few problems that optimizations won’t fix:
- SEO (search engine optimization): SPAs (single-page applications) are harder to index by search engines because the content isn’t available on load time. Therefore, the application is likely to fail on several SEO requirements.
- Slow initial page load: Since the application still needs to be bootstrapped after the page is loaded, there is an initial waiting time until the user can use the application. This results in a bad user experience.
Now, we have two ways to solve this problem.
- Server-Side Rendering (SSR): SSR executes the Angular application on the server. The server will serve the compiled content in a way that search engine crawlers can read it. SSR is the best of both worlds. The server will render the application, but when the JavaScript bundle is loaded, it will turn into a SPA. The result is an application with rich UI/UX that loads quickly at the same time!
- Pre-Rendering: Pre-rendering would run generated static HTML files when we create build, and that is insanely fast. And when the JavaScript bundles are loaded, the browser would take over. What we get after this is Ultra fast loading time + No compromise in the rich SPA experience.
Both the technique solves the issue we have above, but if you see the rendering time that we have observed, it will make sense to choose the later.
Updates in Angular 9
Read MoreHow to implement pre-render Angular applications?
First, you need to add angular universal to your project using this command from the server-side rendering guide
Must use Node 12 or above Version
ng add @nguniversal/express-engine --clientProject project-example
The command will generate all the scripts to run server-side rendering in our application. You need it to generate static pages.
The next step is to transfer the code fragments responsible for creating the express server from server.ts
to a new express-app.ts
file. Below is the code that you should paste into the new file.
// express-app.ts
import 'zone.js/dist/zone-node';
import * as express from 'express';
import { join } from 'path';
// Express server
export const app = express();
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const {AppServerModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap} = require('./dist/server/main');
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
app.set('view engine', 'html');
app.set('views', DIST_FOLDER);
// Example Express Rest API endpoints
// app.get('/api/**', (req, res) => { });
// Serve static files from /browser
app.get('*.*', express.static(DIST_FOLDER, {
maxAge: '1y'
}));
// All regular routes use the Universal engine
app.get('*', (req, res) => {
res.render('index', { req });
});
Once you copy the code remove the express server code from the server.ts
and instead, import it from the express-app.ts
leaving only the code listening to the port.
Server Side Rendering with Angular 10
Read More// server.ts
import { app } from './express-app';
const PORT = process.env.PORT || 4000;
// Start up the Node server
app.listen(PORT, async () => {
console.log(`Node Express server listening on http://localhost:${PORT}`);
});
Further, now add the main code that performs pre-render of our sub-pages. (you also need to install an additional library to create sub-folders using the command npm install mkdirp @types/mkdirp
)
// Prerender.ts
import * as request from 'request-promise';
import * as mkdirp from 'mkdirp';
import { promisify } from 'util';
import { writeFileSync } from 'fs';
import { Express } from 'express';
import { app } from './express-app';
export const ROUTES = [
'/',
'/auth',
'/privacy-policy'
];
const mkdirpAsync = promisify(mkdirp);
function prerender(expressApp: Express, routes: string[]) {
const PORT = process.env.PRERENDER_PORT || 4000;
// Start up the Node server
const server = expressApp.listen(PORT, async () => {
try {
for (const route of routes) {
const result = await request.get(`http://localhost:${PORT}${route}`);
await mkdirpAsync(`dist/browser${route}`);
writeFileSync(`dist/browser${route}/index.html`, result);
}
console.log('Prerender complete.');
server.close();
} catch (error) {
server.close(() => process.exit(1));
}
});
}
prerender(app, ROUTES);
// Work around Solution for https://github.com/angular/angular-cli/issues/7200 (This is just for reference)
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode: 'none',
entry: {
// This is our Express server for Dynamic universal
server: './server.ts',
prerender: './prerender.ts' // <--------------- HERE!!!
},
externals: {
'./dist/server/main': 'require("./server/main")'
},
target: 'node',
resolve: { extensions: ['.ts', '.js'] },
optimization: {
minimize: false
},
output: {
// Puts the output at the root of the dist folder
path: path.join(__dirname, 'dist'),
filename: '[name].js'
},
module: {
noParse: /polyfills-.*\.js/,
rules: [
{ test: /\.ts$/, loader: 'ts-loader' },
{
// Mark files inside `@angular/core` as using SystemJS style dynamic imports.
// Removing this will cause deprecation warnings to appear.
test: /(\\|\/)@angular(\\|\/)core(\\|\/).+\.js$/,
parser: { system: true }
}
]
},
plugins: [
new webpack.ContextReplacementPlugin(
// fixes WARNING Critical dependency: the request of a dependency is an expression
/(.+)?angular(\\|\/)core(.+)?/,
path.join(__dirname, 'src'), // location of your src
{} // a map of your routes
),
new webpack.ContextReplacementPlugin(
// fixes WARNING Critical dependency: the request of a dependency is an expression
/(.+)?express(\\|\/)(.+)?/,
path.join(__dirname, 'src'),
{}
)
]
};
Why hire an AngularJS development company for app development?
Read MoreYou will need to add a new script to package.json
for ease of use.
"scripts": {
...
"prerender": "node dist/prerender",
...
}
And that’s all, now you just need to build an application in SSR mode and run the command "prerender".
npm run build:ssr && npm run prerender
In the dist/browser
directory, you will find sub-folders with index.html
files containing SEO-friendly generated HTML content of the application.
If you are using @angular/service-worker
then you will need to reconfigure it right after the prerender
because the checksum value in the index.html file has changed after the HTML modification. Use the command below to do so.
ngsw-config dist/browser ngsw-config.json
We are a team of expert developers, testers and business consultants who strive to deliver nothing but the best. Planning to build a completely secure and efficient Angular app? 'Hire Angular Developers'.
Conclusion
Pre-render allows us to generate HTML files for every route so that we can serve content faster.
To ensure that clients can only download the files that they are permitted to see, put all client-facing asset files in the /dist
folder and only honor requests for files from the /dist
folder.
Third Rock Techkno is a leading IT services company. We are a top-ranked web, voice and mobile app development company with over 10 years of experience. Client success forms the core of our value system.
We have expertise in the latest technologies including Angular, React Native, iOs, Android, and more. Third Rock Techkno has developed smart, scalable, and innovative solutions for clients across a host of industries.
Our team of dedicated developers combines their knowledge and skills to develop and deliver web and mobile apps that boost business and increase output for our clients.
Looking For Expert Guidance on Your Dream Project?
Our diverse team of industry leading veterans can help you build the most viable solution.
Schedule a free consultation calltest