Skip to content

Commit

Permalink
add brain dump for adding SSR
Browse files Browse the repository at this point in the history
  • Loading branch information
manfredsteyer committed Jul 9, 2021
1 parent 1979bfc commit 606cec2
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 30 deletions.
6 changes: 3 additions & 3 deletions libs/mf-runtime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"name": "@angular-architects/module-federation-runtime",

"license": "MIT",
"version": "12.2.0",
"version": "12.4.0",
"peerDependencies": {
"@angular/common": ">=12.0.0",
"@angular/core": ">=12.0.0"
"@angular/common": ">=12.4.0",
"@angular/core": ">=12.4.0"
},
"dependencies": {
"tslib": "^2.0.0"
Expand Down
2 changes: 1 addition & 1 deletion libs/mf-tools/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@angular-architects/module-federation-tools",
"version": "12.2.1",
"version": "12.4.0",
"license": "MIT",
"peerDependencies": {
"@angular/common": ">=11.0.0",
Expand Down
77 changes: 76 additions & 1 deletion libs/mf/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,83 @@ shared: {

The options passed to shareAll are applied to all dependencies found in your ``package.json``.

This might come in handy in an monorepo scenario and when doing some experiments/ trouble shooting.
This might come in handy in an mono repo scenario and when doing some experiments/ trouble shooting.

### Angular Universal (Server Side Rendering)

Since Version 12.4.0 of this plugin, we support the new _jsdom_-based Angular Universal API for Server Side Rendering (SSR). Please note that SSR *only* makes sense in specific scenarios, e. g. for customer-facing apps that need SEO.

To make use of SSR, you should enable SSR for **all** of your federation projects (e. g. the shell and the micro frontends).

#### Adding Angular Universal BEFORE adding Module Federation

If you start with a new project, you should add Angular Universal BEFORE adding Module Federation:

```
ng add @nguniversal/common --project yourProject
ng add @angular-architects/module-federation --project yourProject
```

Then, adjust the port in the generated ``server.ts``:

```typescript
const PORT = 5000;
```

After this, you can compile and run your application:

```
ng build yourProject && ng run yourProject:server
node dist/yourProject/server/main.js
```

#### Adding Angular Universal to an existing Module Federation project

If you already use ``@angular-architects/module-federation``, you can add Angular Universal this way:

1. Update ``@angular-architects/module-federation`` to the latest version (>= 12.4).

```
npm i @angular-architects/module-federation@latest
```

2. Now, we need to disable asynchronous bootstrapping temporarily. While it's needed for Module Federation, the schematics provided by Angular Universal assume that Angular is bootstrapped in an traditional (synchronous) way. After using these Schematics, we have to enable asynchronous bootstrapping again:

```
ng g @angular-architects/module-federation:boot-async false --project yourProject
ng add @nguniversal/common --project yourProject
ng g @angular-architects/module-federation:boot-async true --project yourProject
```

3. As now we have both, Module Federation and Angular Universal, in place, we can integrate them with each other:

```
ng g @angular-architects/module-federation:nguniversal --project yourProject
```

4. Adjust the used port in the generated ``server.ts`` file:

```typescript
const PORT = 5000;
```

5. Now, you can compile and run your application:

```
ng build yourProject && ng run yourProject:server
node dist/yourProject/server/main.js
```

#### Example

Please find an [example](https://github.com/manfredsteyer/module-federation-plugin-example/tree/ssr
) here in the branch ``ssr``.

#### Trying it out

To try it out, you can checkout the ``main`` branch of our [example](https://github.com/manfredsteyer/module-federation-plugin-example). After installing the dependencies (``npm i``), you can repeat the steps for adding Angular Universal to an existing Module Federation project described above twice: Once for the _project shell and the port 5000_ and one more time for the _project mfe1 and port 3000_.

### Pitfalls when sharing libraries of a Monorepo

Expand Down
6 changes: 3 additions & 3 deletions libs/mf/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@angular-architects/module-federation",
"version": "12.3.0-beta.9",
"version": "12.4.0",
"license": "MIT",
"repository": {
"type": "GitHub",
Expand All @@ -17,8 +17,8 @@
"schematics": "./collection.json",
"builders": "./builders.json",
"dependencies": {
"ngx-build-plus": "^12.1.0-beta.3",
"@angular-architects/module-federation-runtime": "^12.2.0",
"ngx-build-plus": "^12.2.0",
"@angular-architects/module-federation-runtime": "^12.4.0",
"word-wrap": "^1.2.3",
"callsite": "^1.0.0",
"node-fetch": "^2.6.1"
Expand Down
16 changes: 0 additions & 16 deletions libs/mf/src/schematics/mf/schematic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ export default function config (options: MfSchematicSchema): Rule {
projectConfig.architect['extract-i18n'].options.extraWebpackConfig = configPath;
}

updateServerBuilder(projectConfig, configPath);
const ssrMappings = generateSsrMappings(workspace, projectName);

tree.overwrite(workspaceFileName, JSON.stringify(workspace, null, '\t'));
Expand All @@ -227,21 +226,6 @@ export default function config (options: MfSchematicSchema): Rule {
}
}

export function updateServerBuilder(projectConfig: any, configPath: string) {

if (projectConfig?.architect?.server) {
projectConfig.architect.server.builder = 'ngx-build-plus:server';
}

if (projectConfig?.architect?.server?.options) {
projectConfig.architect.server.options.extraWebpackConfig = configPath;
}

if (projectConfig?.architect?.server?.configurations?.production) {
projectConfig.architect.server.configurations.production.extraWebpackConfig = configPath;
}
}

function generateRemoteConfig(workspace: any, projectName: string) {
let remotes = '';
for (const p in workspace.projects) {
Expand Down
7 changes: 1 addition & 6 deletions libs/mf/src/schematics/nguniversal/schematic.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { NgUniversalSchema } from "./schema";
import { Rule, chain, externalSchematic } from '@angular-devkit/schematics';
import path = require("path");
import { generateSsrMappings, getWorkspaceFileName, updateServerBuilder, adjustSSR } from "../mf/schematic";
import { generateSsrMappings, getWorkspaceFileName, adjustSSR } from "../mf/schematic";

export default function nguniversal (options: NgUniversalSchema): Rule {

Expand All @@ -23,15 +22,11 @@ export default function nguniversal (options: NgUniversalSchema): Rule {
const projectConfig = workspace.projects[projectName];

const projectSourceRoot: string = projectConfig.sourceRoot;
const projectRoot: string = projectConfig.root;

const configPath = path.join(projectRoot, 'webpack.config.js').replace(/\\/g, '/');

if (!projectConfig?.architect?.server) {
console.error('No server target found. Did you add Angular Universal? Try ng add @nguniversal/common');
}

updateServerBuilder(projectConfig, configPath);
const ssrMappings = generateSsrMappings(workspace, projectName);

tree.overwrite(workspaceFileName, JSON.stringify(workspace, null, '\t'));
Expand Down
35 changes: 35 additions & 0 deletions libs/mf/tutorial/braindump-ssr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## Adding Angular Universal to an Module Federation Project

This brain dump shows how to add Angular Universal to our [example](https://github.com/manfredsteyer/module-federation-plugin-example).

```
npm i @angular-architects/module-federation@latest --registry http://localhost:4873
ng g @angular-architects/module-federation:boot-async false --project shell
ng add @nguniversal/common --project shell
ng g @angular-architects/module-federation:boot-async true --project shell
ng g @angular-architects/module-federation:nguniversal --project shell
ng g @angular-architects/module-federation:boot-async false --project mfe1
ng add @nguniversal/common --project mfe1
ng g @angular-architects/module-federation:boot-async true --project mfe1
ng g @angular-architects/module-federation:nguniversal --project mfe1
Adjust projects\shell\src\server.ts
const PORT = 5000;
Adjust projects\mfe1\src\server.ts
const PORT = 3000;
ng build mfe1 && ng run mfe1:server
node dist/mfe1/server/main.js
ng build shell && ng run shell:server
node dist/shell/server/main.js
```


0 comments on commit 606cec2

Please sign in to comment.