Skip to content

feat: create "Deployment strategy for Micro Frontends" post #150

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# Deployment strategy for Micro Frontends

Check warning on line 1 in content/posts/unpublished/deployment-strategy-for-micro-frontends/post.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/posts/unpublished/deployment-strategy-for-micro-frontends/post.md#L1

[Google.Headings] 'Deployment strategy for Micro Frontends' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Deployment strategy for Micro Frontends' should use sentence-style capitalization.", "location": {"path": "content/posts/unpublished/deployment-strategy-for-micro-frontends/post.md", "range": {"start": {"line": 1, "column": 3}}}, "severity": "WARNING"}

The ultimate guide for deploying Micro Frontends with the Backbase web-base Docker image.

![](assets/banner.png)

Authors: Pablo Villoslada Puigcerber

Check warning on line 7 in content/posts/unpublished/deployment-strategy-for-micro-frontends/post.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/posts/unpublished/deployment-strategy-for-micro-frontends/post.md#L7

[Google.Colons] ': P' should be in lowercase.
Raw output
{"message": "[Google.Colons] ': P' should be in lowercase.", "location": {"path": "content/posts/unpublished/deployment-strategy-for-micro-frontends/post.md", "range": {"start": {"line": 7, "column": 8}}}, "severity": "WARNING"}
Date: unpublished
Category: frontend

tags: angular,docker,frontend,micro-frontends,module-federation,web

---

## Introduction

You need to keep two things in mind when deploying Micro Frontends: first of all, you have to coordinate the deployment of two or more applications; and second, you must tell your shell app where to find the remotes.

Other than that, there are no big differences with any other deployment.

## Where are the remotes?

In [routing between the shell and the remote](2024/05/15/maintaining-legacy-code-with-micro-frontends#routing-between-the-shell-and-the-remote) you can find how to configure the routing but now, instead of using a static `remoteEntry`, you have to make it dynamic to cater for different environments.

To make it dynamic, you need to add a new property to your environment files. You can keep the URL hardcoded for your local config.

```typescript
export const environment: Environment = {
...,
mfeUrl: 'http://localhost:4207/remoteEntry.js',
};
```

And make use of an environment variable in your production config.

```typescript
export const environment: Environment = {
...,
mfeUrl: '${MFE_URL}remoteEntry.js',
};
```

Then you just need to set the new `mfeUrl` property in your routing configuration.

```typescript
import { environment } from '../environments/environment';

const remoteWrapperOptions = {
elementName: 'remote-element',
exposedModule: './web-components',
remoteEntry: environment.mfeUrl,
remoteName: 'remoteApp',
} as WebComponentWrapperOptions;
```

## Configure Docker

Configuring Docker it's going to entirely depend on your CI/CD set-up as you might want to build the app outside of Docker as part of your actions or pipelines.

For this example, with the goal of deploying the app locally, you can have an optimized multi-stage build with two stages: one for building the app, and another one to copy the output into the [web-base](https://backbase.io/developers/documentation/web-devkit/reference/web-base/) that runs the NGINX server.

Create a Dockerfile for your shell.
```shell
FROM node:16 AS builder
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
COPY package*.json ./
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm install
# Bundle app source
COPY . .
RUN NODE_OPTIONS=--max-old-space-size=4096 npm run build

FROM repo.backbase.com/backbase-docker-releases/web-base:2.1.1
# Copy the build output
COPY --from=builder /usr/src/app/dist/shell /statics
```

And another one for the remote.
```shell
FROM node:18 AS builder
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
COPY package*.json ./
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm install
# Bundle app source
COPY . .
RUN NODE_OPTIONS=--max-old-space-size=4096 npm run build

FROM repo.backbase.com/backbase-docker-releases/web-base:2.1.1
# Copy the build output
COPY --from=builder /usr/src/app/dist/remote-app /statics
```

## Local deployment

### Custom CSP configuration

Check warning on line 98 in content/posts/unpublished/deployment-strategy-for-micro-frontends/post.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/posts/unpublished/deployment-strategy-for-micro-frontends/post.md#L98

[Google.Headings] 'Custom CSP configuration' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Custom CSP configuration' should use sentence-style capitalization.", "location": {"path": "content/posts/unpublished/deployment-strategy-for-micro-frontends/post.md", "range": {"start": {"line": 98, "column": 5}}}, "severity": "WARNING"}

Within the Docker container, the JavaScript of the remote app is going to load from a different port and that's not allowed by the default CSP configuration.

To overcome this problem, create a new file named `20-csp.conf` with the following content:

```shell
add_header Content-Security-Policy-Report-Only "default-src 'none'; script-src 'self' blob: ${MFE_URL}; media-src 'self'; connect-src 'self' ${API_ROOT::url_origin} ${AUTH_URL::url_origin}; img-src 'self'; style-src 'self' 'unsafe-inline' ; base-uri 'self'; object-src 'none'; font-src 'self'" always;
```

And add this line at the end of your shell's Dockerfile:
```shell
COPY 20-csp.conf /nginx-config/server/index/20-csp.conf
```

It overrides the default CSP configuration allowing the URL defined in the `MFE_URL` environment variable.

### NGINX reverse proxy

Serving the Angular app locally you can configure the [Webpack proxy](https://v17.angular.io/guide/build#proxying-to-a-backend-server) to divert the `/api` calls to an actual backend server. But how can you do the same when deploying the app with Docker? Setting the [NGINX reverse proxy](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/) prevents the CORS issues of having frontend and backend on different domains.

Create a new `15-proxy.conf` file:
```bash
location ^~ /api/ {
proxy_set_header ${API_KEY} ${API_VALUE};
proxy_pass ${API_URL};
}
```

And add an extra line to your Dockerfile:
```bash
COPY 15-proxy.conf /nginx-config/server/15-proxy.conf
```

Repeat this step for the remote app and keep in mind that depending on your backend server configuration you might need extra headers.

### Docker Compose

Check warning on line 134 in content/posts/unpublished/deployment-strategy-for-micro-frontends/post.md

View workflow job for this annotation

GitHub Actions / vale

[vale] content/posts/unpublished/deployment-strategy-for-micro-frontends/post.md#L134

[Google.Headings] 'Docker Compose' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Docker Compose' should use sentence-style capitalization.", "location": {"path": "content/posts/unpublished/deployment-strategy-for-micro-frontends/post.md", "range": {"start": {"line": 134, "column": 5}}}, "severity": "WARNING"}

Although you could run the `docker` command individually for each image, [Compose](https://docs.docker.com/compose/) is going to help you streamline the process and also set all the environment variables.

Create `compose.yaml` in the root of your project and adjust accordingly, as this config works with the [API Sandbox](https://backbase.io/developers/documentation/api-sandbox/).
```bash
services:
shell:
build:
context: ./shell
secrets:
- npmrc
ports:
- target: 8080
published: 8080
environment:
API_KEY: X-Sdbxaz-Api-Key
API_ROOT: /api/
API_URL: https://app.bus.sdbxaz.azure.backbaseservices.com/api/
API_VALUE: ''
AUTH_CLIENT_ID: bb-web-client
AUTH_REALM: customer
AUTH_SCOPE: openid
AUTH_URL: https://identity.bus.sdbxaz.azure.backbaseservices.com/auth/
BASE_HREF: /
HOSTNAME: localhost
MFE_URL: http://localhost:4207/
PORT: 8080
remoteApp:
build:
context: ./remote-app
secrets:
- npmrc
ports:
- target: 4207
published: 4207
environment:
API_KEY: X-Sdbxaz-Api-Key
API_ROOT: /api/
API_URL: https://app.bus.sdbxaz.azure.backbaseservices.com/api/
API_VALUE: ''
AUTH_CLIENT_ID: bb-web-client
AUTH_REALM: customer
AUTH_SCOPE: openid
AUTH_URL: https://identity.bus.sdbxaz.azure.backbaseservices.com/auth/
BASE_HREF: /
HOSTNAME: localhost
PORT: 4207

secrets:
npmrc:
file: ~/.npmrc
```

Now run `docker compose up` to build both images and if everything goes all right, you should be able to open http://localhost:8080/ in your browser and see real data.

## Conclusion

You might want to deploy each separately, or you may even have different teams working in each app, but as long as you tell the shell where the remotes are, deploying Micro Frontends is no different to deploying your regular Angular app.
Loading