Skip to content

Commit

Permalink
feat: support Angular v17
Browse files Browse the repository at this point in the history
This commit updates angular-prerender to work with Angular v17. It also removes everything related
to the now deprecated @nguniversal package.

BREAKING CHANGE: Using Angular v16 and or any package from the @nguniversal scope is not supported
any longer.
  • Loading branch information
chrisguttandin committed Jan 28, 2024
1 parent bcabb09 commit a46bc8b
Show file tree
Hide file tree
Showing 16 changed files with 115 additions and 398 deletions.
42 changes: 7 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ angular-prerender is available on [npm](https://www.npmjs.com/package/angular-pr
npm install angular-prerender --save-dev
```

In case you used all the default settings of the CLI angular-prerender will be able to pick up all the necessary information on its own. You can run it on the command line by only specifying the browser and server target.
In case you used all the default settings of the CLI angular-prerender will be able to pick up all the necessary information on its own. You can run it on the command line by only specifying the browser target.

```shell
npx angular-prerender --browser-target universe:build --server-target universe:server
npx angular-prerender --target universe:build
```

It is also possible to skip the explicit installation of angular-prerender.
Expand All @@ -29,21 +29,16 @@ The following is a complete example which will generate a very basic static Angu
```shell
npx @angular/cli new universe --routing
cd universe
ng generate universal --project universe
ng add @angular/ssr
npm install angular-prerender --save-dev
ng build
ng run universe:server
npx angular-prerender --browser-target universe:build --server-target universe:server
npx angular-prerender --target universe:build
```

## Arguments

In some scenarios angular-prerender will not be able to grab all the information by analyzing the angular.json file alone. In that case you can help it by specifying some command line arguments.

### --browser-target

This lets you specify the name of the target of your client app. The Angular CLI will normally call it "build" and this is also used as a default value. It is also possible to use a full target specifier which does also include the project and an optional configuration separated by colons. This works similar as the target parameter of the [ng run command](https://angular.io/cli/run).

### --config

The config option expects a path (including the filename) to the angular.json file of your project. By default it will look for it in the current working directory.
Expand All @@ -56,29 +51,6 @@ This option can be used to tell angular-prerender not to render specified routes
npx angular-prerender --exclude-routes /do-not-render-1 /do-not-render-2
```

Alternatively routes can also be excluded when setting the status code as described below.

### --ignore-status-code

When set to false this flag will make sure that status codes set on the response will not be ignored. An example of a component which sets the status code looks as follows:

```typescript
import { Component, Inject } from '@angular/core';
import { RESPONSE } from '@nguniversal/express-engine/tokens';
import { Response } from 'express';

@Component({
// ...
})
class NotFoundComponent {
constructor(@Inject(RESPONSE) response: Response) {
response.status(404);
}
}
```

If status codes are not ignored any route which sets the status code to 300 or above will be excluded.

### --include-routes

This option can be used to tell angular-prerender to explicitly render the given routes even though they could not be detected automatically.
Expand Down Expand Up @@ -171,14 +143,14 @@ In case any of the newly discovered routes is one of the routes defined with [`-

This option allows you to specify a path to a [Scully](https://scully.io) config file. `@scullyio/scully` and the respective plugins need to be installed for this to work. So far only the plugins specified as [`defaultPostRenderers`](https://scully.io/docs/Reference/config/#interface) and plugins of type [`routeProcess`](https://scully.io/docs/Reference/plugins/types/route-process) get applied.

### --server-target
### --target

This lets you specify the name of the target of your server app. The Angular CLI will normally call it "server" and this is also used as a default value. It is also possible to use a full target specifier which does also include the project and an optional configuration separated by colons. This works similar as the target parameter of the [ng run command](https://angular.io/cli/run).
This lets you specify the name of the target of your client app. The Angular CLI will normally call it "build" and this is also used as a default value. It is also possible to use a full target specifier which does also include the project and an optional configuration separated by colons. This works similar as the target parameter of the [ng run command](https://angular.io/cli/run).

### --verbose (-v)

This flag enables more detailed log messages.

## Acknowledgement

This command line tool is only possible by bringing together the great power of [Angular Universal](https://github.com/angular/universal) (which is now on its way into the main [Angular repository](https://github.com/angular/angular)) and [Guess.js](https://github.com/guess-js) (which provides an excellent parser to retrieve the routes of an Angular app).
This command line tool is only possible by bringing together the great power of [Angular Universal](https://github.com/angular/universal) (which is now included in the [Angular CLI repository](https://github.com/angular/angular-cli)) and [Guess.js](https://github.com/guess-js) (which provides an excellent parser to retrieve the routes of an Angular app).
28 changes: 5 additions & 23 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import yargs from 'yargs';
import { peerDependencies } from './constants.js';
import { coerceParameterValues } from './functions/coerce-parameter-values.js';
import { coerceTargetSpecifier } from './functions/coerce-target-specifier.js';
import { loadPeerDependencies } from './functions/load-peer-dependencies.js';
import { loadScullyConfigAndPlugins } from './functions/load-scully-config-and-plugins.js';
import { readProperty } from './functions/read-property.js';
import { ICommandLineArguments } from './interfaces';
Expand All @@ -30,12 +29,6 @@ if (missingPeerDependencies.length > 0) {
(async () => {
const commandLineArguments = (<yargs.Argv<ICommandLineArguments>>yargs(argv.slice(2)))
.help()
.option('browser-target', {
coerce: coerceTargetSpecifier,
default: 'build',
describe: 'specify the target inside your angular.json file which is used to build the single page app',
type: 'string'
})
.option('config', {
default: join(cwd(), 'angular.json'),
describe: 'specify the path to the angular.json file',
Expand All @@ -48,11 +41,6 @@ if (missingPeerDependencies.length > 0) {
string: true,
type: 'array'
})
.option('ignore-status-code', {
default: true,
describe: 'set this to false if you want to not render routes that return a status code of 300 or above',
type: 'boolean'
})
.option('include-routes', {
default: <ICommandLineArguments['includeRoutes']>[],
describe: 'specify routes to include',
Expand Down Expand Up @@ -80,10 +68,10 @@ if (missingPeerDependencies.length > 0) {
describe: 'specify the path to the Scully configuration file',
type: 'string'
})
.option('server-target', {
.option('target', {
coerce: coerceTargetSpecifier,
default: 'server',
describe: 'specify the target inside your angular.json file which is used to build the server side code',
default: 'build',
describe: 'specify the target inside your angular.json file which is used to build the single page app',
type: 'string'
})
.option('verbose', {
Expand All @@ -99,27 +87,22 @@ if (missingPeerDependencies.length > 0) {
}

const {
browserTarget,
config,
excludeRoutes,
ignoreStatusCode: shouldIgnoreStatusCode,
includeRoutes,
parameterValues: nestedParameterValuesMap,
preserveIndexHtml: shouldPreserveIndexHtml,
recursive: isRecursive,
scullyConfig: scullyConfigFile,
serverTarget,
target,
verbose: isVerbose
} = commandLineArguments;
const { prerender } = await import('./functions/prerender.js');
const { expressResponseToken } = await loadPeerDependencies(cwd(), require);
const { config: scullyConfig, plugins: scullyPlugins } = await loadScullyConfigAndPlugins(cwd(), require, scullyConfigFile);

prerender(
browserTarget,
config,
excludeRoutes,
expressResponseToken,
includeRoutes,
isRecursive,
isVerbose,
Expand All @@ -128,8 +111,7 @@ if (missingPeerDependencies.length > 0) {
require,
scullyConfig,
scullyPlugins,
serverTarget,
shouldIgnoreStatusCode,
target,
shouldPreserveIndexHtml
);
})();
19 changes: 13 additions & 6 deletions src/functions/bind-render-function.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { IMainExports } from '../interfaces';
import type { StaticProvider } from '@angular/core';
import { isModule } from '../guards/module.js';
import { IMainExports, IRenderUtilsExports } from '../interfaces';
import { TRenderApplicationFunction } from '../types';

export const bindRenderFunction = async (main: string) => {
const {
default: { AppServerModule, renderModule }
} = <{ default: IMainExports }>await import(main);
export const bindRenderFunction = async (main: string, renderUtils: string) => {
const { default: bootstrapOrModule } = <IMainExports>await import(main);
const { renderApplication, renderModule } = <IRenderUtilsExports>await import(renderUtils);

return renderModule.bind(null, AppServerModule);
if (isModule(bootstrapOrModule)) {
return ({ document, platformProviders, url }: Parameters<TRenderApplicationFunction>[1]) =>
renderModule(bootstrapOrModule, { document, extraProviders: <undefined | StaticProvider[]>platformProviders, url });
}

return renderApplication.bind(null, bootstrapOrModule);
};
24 changes: 0 additions & 24 deletions src/functions/load-peer-dependencies.ts

This file was deleted.

Loading

0 comments on commit a46bc8b

Please sign in to comment.