Managing Distributed Script Versions in Micro-Frontend Architecture

Mehmet Ersan Uzun
Trendyol Tech
Published in
5 min readMar 14, 2022

First of all, let’s give information about the Micro Frontend Architecture that we use in the seller center.

There are different practices to implement Micro Frontend Architecture

  1. Single SPA framework that combines multiple JavaScript micro frontend applications on the same page without refreshing the page,
  2. Multiple single-page micro frontend application lives at different URLs.
  3. Isolating Micro apps into Iframes using Windows. Post Message APIs and libraries to coordinate. IFrames share APIs exposed by their parent window.
  4. Different modules to communicate over a shared events bus. Each module is working on its own framework, as long as it handles incoming and outgoing events.

In Seller Center Panel, We use the above as micro frontend architecture. Every team has SPA application and there is soft navigation (without refreshing page) between pages in one application. On the other hand, there is hard navigation (refreshing page) between SPA applications. For more detailed information about micro frontend architecture in the seller center panel, you can read this article.

Why do we need this architecture?

In Trendyol, we plan our applications to work scalable in multi datacenters so that we can provide instant service to thousands of vendors. The starting point of this architecture was to facilitate Multi DC transition. Because we were making all the FE application deployments to k8s as servers and we were pulling the scripts from these servers.

When Multi DC transition was started without this application, all the deployments would have to be deployed to multiple data centers as well. This meant that all child applications would have multiple servers in multiple datacenters.

Every child application which was deployed on k8s machines had to serve a manifest.json file. This file contains script references.

The seller-center-root-app(it is an express application and serves the index.html file) to register child applications to index.html, send a request to manifest.json file for all child applications in the current route.

manifest.json and child applications scripts are only static files that depend on deployments, so they can be served from CDN instead of k8s deployments. But if scripts and manifest.jsonwere served from CDN, a problem would show up.

The problem is getting the latest script reference that exists in manifest.json. The reason why themanifest.json the filename is not changeable, this file has cache CDN. This cache should be purged for every deployment. For this reason, it will be good to not serve manifest.json from CDN. It is enough to know what is the latest script reference.

The latest version of script reference can be stored somewhere else. A question is coming, where should it be?

This responsibility is not of the seller-center-root-app. We decided to create a layer that stores all application script references. And seller-center-root-app should know only this application for script references. All the script logic should be handled in this application. It creates an abstraction for script references.

Script-keeper Structure

As said above, it has simple responsibility. It is keeping script references.

Developed with couchbase and NestJS. We store the script references in couchbase. Each document has an id with the same child app name.

document id

The document data stores the script reference information.

{
"src": "http://bla.cdn.com/child-app-1/js/app.1234.js",
"appName": "child-app-1",
"chunk": "" # If you have chunk file put in there
}

Has 2 main endpoints.

  • Upsert script
  • Get script by application name

Upsert Script

This endpoint stores the given script reference in the couchbase. For this, the endpoint expects the following request body.

export default class ScriptRequest {
appName: string;
src: string;
chunk?: string;
}

If there is no script reference before, it creates a new document and inserts the couchbase. Otherwise, update it.

We need to integrate the endpoint for all child application pipelines. After sending scripts to any CDN, the endpoint should be called with expected parameters.

We wanted to automate the process of updating script reference in script-keeper application, so that we add a new stage to .gitlab-ci.yml

To achieve this, we created a base GitLab pipeline stage. script-keeper.yml file contains GitLab pipeline definitions.

And script-keeper-upload.sh file is used to parse the latest application script reference from manifest.json.

// dist/manifest.json
{
"app.js": "http://bla.cdn.com/child-app-1/js/app.1234.js",
"chunk-vendors.js": "http://bla.cdn.com/child-app-1/js/chunk-vendors.234.js",
}

script-keeper-upload.sh uses above manifest.json to call script-keeper upsert endpoint. It gets app.js and chuck-vendors.js field from dist/manifest.json.

This script sends a POST request to /script endpoint which is in the script-keeper application. The following example is a request body. src shows use to latest script reference ofchild-app-1 application.

{
"src": "http://bla.cdn.com/child-app-1/js/app.1234.js",
"appName": "child-app-1",
"chunk": "" # If you have chunk file put in there
}

Get script by application name

We registered the scripts to script-keeper with the above flow. Now, we can get them from it.

In seller-center-root-app, we send a request to the script-keeper application.

After getting script reference the only need to send the appSrc to index.html. Now the application is ready to start up.

index.html child application script reference with the chunk

Conclusion

With this architect, the Multi DC transition of seller-center-root-app became easier. Other teams had to do multi dc deployments. It also provides an abstraction between the seller-center-root-app and script references. Now, script references can be stored anywhere.

I hope you find this helpful, please let me know your comments

--

--