Security News
PyPI’s New Archival Feature Closes a Major Security Gap
PyPI now allows maintainers to archive projects, improving security and helping users make informed decisions about their dependencies.
angular-ssr
Advanced tools
The purpose of this library is to allow your application to support server-side rendering of your Angular 4+ applications with minimal code changes and mimimal difficulty. It supports both Angular CLI projects and projects that use custom webpack configurations. It works out of the box with @angular/material
with no hot-fixes or workarounds! It also requires zero changes to your application code: you won't have to create separate @NgModule
s, one for the server-side rendered application and one for the regular client application. You can just take your Angular code as-is and follow the steps below to get server-side rendering working.
There are two ways you can use angular-ssr
:
ng build
, and then invoke ng-render
from node_modules/.bin
. This will result in several steps being taken:
tsconfig.json
and some other configuration elements to compile your application to a temporary directory and load the resulting JavaScript code (application code + .ngfactory.js
files) into memory./
, /foo
, /bar
).html
file in dist
(or, if you specified an alternate output directory using --output
, it will write the files there). It instantiates the application using the existing dist/index.html
file that was produced as part of your normal application build as a template. The pre-rendered content will be inserted into that template and written out as a new .html
file based on the route: e.g., /foo/index.html
.ng-render
. But that's alright. It just means that you will have to build a separate webpack program output: either a NodeJS HTTP server, or a NodeJS application whose sole purpose is to do prerendering. You will follow these rough steps:
angular-ssr
as a dependency: npm install angular-ssr --save
angular-ssr
.webpack.config.js
and just add an additional output, or you create an entirely new webpack-server.config.js
which will serve as your SSR webpack configuration. Regardless of how you accomplish it, you will ultimately need to produce two programs from webpack:
angular-ssr
will not integrate directly with the HTTP server anyway. It just exposes a very simple API to get pre-rendered HTML documents, and you can integrate this with your server in whichever way makes the most sense for your application./a
, /b
, /c
, etc.). In this case, since all routes are known in advance and none of them take any URL parameters, we can just pre-render each route at build time and spit out some .html
files./blog/post/1
, /blog/user/3
, etc. In this case, you will need to do on-demand server-side rendering. No problem! In this use-case, it makes sense to build a small HTTP server using express or koa and to write a few lines of code to integrate with angular-ssr
. Then from inside your server, you can demand render and cache particular routes with arguments like /blog/post/1
. I will show you some examples of how to do this below.If your application was generated by ng new
and does not use any custom webpack configuration, then you will be able to use the ng-render
CLI tooll to automatically pre-render your application routes into static .html
files. It is worth emphasizing that this use case is the easiest, but also the least flexible. If you need on-demand rendering, or if you have custom webpack configurations, then you should skip down to the examples below as they will cover your use-case better than this section.
But, in the event that you do have a simple ng cli
application, you can give angular-ssr
a whirl just by doing:
npm install angular-ssr --save
ng build
./node_modules/.bin/ng-render
It should spit out some messages like:
[info] Writing rendered route / to /Users/bond/proj/dist/index.html
[info] Writing rendered route /foo to /Users/bond/proj/dist/foo/index.html
[info] Writing rendered route /bar to /Users/bond/proj/dist/bar/index.html
You can then do cd dist
and run:
npm install -g http-server
http-server .
Then when you load the application by hitting http://localhost:8080
, you should see the pre-rendered document in the initial HTTP response (for each route in your application).
Let's get this use-case out of the way first, because I think it is likely to be the most common usage of angular-ssr
.
You have an HTTP server application that you build as part of your application using webpack. Your HTTP server is written in TypeScript. (If your HTTP server is written in JavaScript, the library will still work in the same way, but you won't be able to copy-paste the code below.)
When you build your application, you are outputting two targets: your actual Angular client application, and your HTTP server application. We are going to focus on the server application here because there will be zero changes to your application code.
Your actual HTTP server code will look something like the following:
import 'reflect-metadata';
import {
ApplicationFromModule,
fileFromString,
routeToPath,
} from 'angular-ssr';
import {join} from 'path';
import {AppModule} from '../src/app/app.module';
const dist = join(process.cwd(), 'dist');
const templateDocument = fileFromString(join(dist, 'index.html'));
if (templateDocument.exists() === false) {
throw new Error('dist/index.html must exist because it is used as an SSR template');
}
const application = new ApplicationFromModule(AppModule);
application.templateDocument(templateDocument.content());
// Pre-render all routes that do not take parameters (angular-ssr will discover automatically)
const prerender = async () => {
const snapshots = await renderer.prerender();
return snapshots.subscribe(
snapshot => {
app.get(snapshot.uri,
(req, res) => res.send(snapshot.renderedDocument));
}).toPromise();
};
prerender();
// On-demand rendering for routes that do take parameters
app.get('/blog/:postId',
async (req, res) => {
try {
const snapshot = await application.renderRoute(req.url); // has internal cache
res.send(snapshot.renderedDocument);
}
catch (exception) {
res.send(templateDocument.content()); // fall back on client-side rendering
}
});
If your application does not fall into the categories described above (i.e., you do not need on-demand server-side rendering of all URLs), then perhaps your application falls into another category: single-use server-side rendering as part of the application build process.
In this case, your code will look similar to the HTTP server code above, but instead of integrating with express, you will simply use ApplicationRenderer
to pre-render all application routes and write them to static .html
files, which you can then serve with the HTTP server of your choosing. Again: this case only makes sense if you do not need on-demand rendering of all application routes.
In this case, your code will look something like this:
import 'reflect-metadata';
import {
ApplicationFromModule,
ApplicationRenderer,
HtmlOutput,
fileFromString,
pathFromString
} from 'angular-ssr';
import {join} from 'path';
import {AppModule} from '../src/app.module';
const dist = join(process.cwd(), 'dist');
const templateDocument = fileFromString(join(dist, 'index.html'));
if (templateDocument.exists() === false) {
throw new Error('Build output dist/index.html must exist prior to prerender');
}
const application = new ApplicationFromModule(ServerModule);
application.templateDocument(templateDocument.content());
const html = new HtmlOutput(pathFromString(dist));
const renderer = new ApplicationRenderer(application);
renderer.renderTo(html)
.then(() => {
console.log('Rendering complete');
})
.catch(exception => {
console.error('Failed to render', exception);
});
I am in the process of building out some more complete example applications over the next day or two. In the meantime, if you have questions you want answered, you can email me at cb@clbond.org
or post an issue in this repository and I would be more than happy to answer!
Christopher Bond
FAQs
Angular server-side rendering implementation
The npm package angular-ssr receives a total of 112 weekly downloads. As such, angular-ssr popularity was classified as not popular.
We found that angular-ssr demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now allows maintainers to archive projects, improving security and helping users make informed decisions about their dependencies.
Research
Security News
Malicious npm package postcss-optimizer delivers BeaverTail malware, targeting developer systems; similarities to past campaigns suggest a North Korean connection.
Security News
CISA's KEV data is now on GitHub, offering easier access, API integration, commit history tracking, and automated updates for security teams and researchers.