This article was originally written in Ara blog.

GatsbyJS is the most popular framework to create static websites. In the software industry, the concept of static site generators is not recent but it’s becoming more popular thanks to the recent evolution of the JavaScript technologies and the introduction of JAMstack.

GatsbyJS enable us to deliver fast and reliable websites that are easy and cheap to host in any cloud provider, for instance, Zeit, Netlify, and others are services that make easier this duty.

JAMstack and AWS Lambda

The main characteristic of JAMstack is that the computing resources are provisioned on-demand only during build-time to generate the static pages, commonly using a serverless CI/CD tool such as CircleCI or Travis CI, which free us of managing dedicated servers.

GatsbyJS explanatory diagram

AWS Lambda works in a similar way, it runs a function triggered by a webhook, commonly using a lambda integration with other AWS services such as API Gateway, SNS, SQS and more.

Following this premise, we can deploy a lambda function that generates and stores HTML inside an S3 bucket or why not, a lambda function that renders HTML on demand.

What do Microfrontends role play here?

Microfronteds like Microservices enable teams to develop and ship features independently.

The level of isolation enables us to integrate different frameworks into the same page. However it doesn’t mean that we should mix frameworks arbitrarily, we should define standard frameworks and libraries across the company.

On the other hand, Frontend technologies evolve fast and the true fact is that at some point we need to move to another framework. Therefore, Microfrontends give us the flexibility to gradually switch to another one without rebuilding the Frontend from scratch.

The scenario

We can imagine that we’re a media company that have a lot of websites shipped across the world that are maintained by different teams. We love React but we’ve fallen in love with VueJs in the last years, so it became our standard library to develop the UI.

Our product team wants to experiment with a new media website and the JAMstack fits in the solution, but we realized that the current frameworks for VueJS don’t have the necessary features that we need.

Then we discovered that GatsbyJS has what we need. But we have another problem, the new website needs to reuse some views that were developed using VueJS previously, we could migrate those views to React but we don’t have enough time and we don’t want to maintain both in the future.

Luckily one of our members recently read about Microfrontends and suggested it. We said, “why not, let’s give it a try”.

What is Ara Framework?

Ara is a framework to easily develop and integrate Micro-frontends using Airbnb’s Hypernova. We created a base architecture called Nova to server-side include Nova views. You can read more about it here.

Recently we brought a new concept called Nova Bridge what we’ll explain in this article.

Microfrontend (Nova)

Hypernova Lambda is an implementation of Airbnb’s Hypernova for AWS Lambda. Hypernova is service to server-side render JavaScript views that are hydrated on the browser to make them dynamic, it’s also known as universal rendering.

In Ara Framework we commonly called Nova to the Hypernova services.

Creating a Microfrontend (Nova)

We need to install the Ara CLI to perform some common tasks such as generate nova services, run hypernova lambda locally and serve the client-side scripts.

$ npm install -g ara-cli

Once the CLI is installed we can generate a new Nova service running the following command:

$ ara new:nova -t vue novas/global

The generated project contains a basic setup. We kept it simple to make it. customizable.

Entry point:

The file src/index.js contains the entry point for the Hypernova server. It uses Express by default but we’ll implement AWS Lambda later.

Example component:

The src/components/Example.vue file renders a basic view using the title prop.

We can run the service using this command:

$ yarn dev

Once the Hypernova server is running we will see the next message.

We can test the service making a POST request to http://localhost:3000/batch using the following payload:

{

"uuid": {

"name": "Example",

"data": {

"title": "Ara Framework"

}

}

}

The response should be something like:

{

"success": true,

"error": null,

"results": {

"uuid": {

"name": "Example",

"html": "<div data-hypernova-key=\"Example\" data-hypernova-id=\"cfd4b502-f9a4-4475-9168-233595ea4489\"><h1 data-server-rendered=\"true\">Ara Framework</h1></div>

<script type=\"application/json\" data-hypernova-key=\"Example\" data-hypernova-id=\"cfd4b502-f9a4-4475-9168-233595ea4489\"><!--{\"title\":\"Ara Framework\"}--></script>",

"meta": {},

"duration": 11.534634,

"statusCode": 200,

"success": true,

"error": null

}

}

}

We can notice the response contains the generated HTML for the Example view.

Implementing Hypernova Lambda

First, we need to install hypernova-lambda .

$ yarn add hypernova-lambda

We need to modify the entry point to use hypernova-lambda .

src/index.js

We also need to remove the NodemonPlugin in webpack.config.js

{

...

plugins: [

new VueLoaderPlugin(),

new NodemonPlugin() // Remove Nodemon plugin

]

}

We can run the lambda function locally using the CLI:

$ ara run:lambda

Also, we can serve the client script locally using an S3 local server:

$ ara run:lambda --asset

We can access to the client-side scripts using http://127.0.0.1:4568/assets/client.js

For this demo, we’ll test hypernova lambda locally. I won’t cover the deployment approach, it’s up to you.

GatsbyJS project

GatsbyJS has it’s own CLI to perform common tasks such as create a project, run a development server, build the website and more.

First, we need to install it:

$ npm install -g gatsby-cli

We can use the CLI to create a new project:

$ gatsby new gatsby-site

We can run the development server:

$ yarn develop

This command compiles the assets and runs a development server on http://localhost:8000/

Home page for GatsbyJS project

We have our Nova service and Gatsby running, it’s time to integrate our Example view into a Gatsby page.

Nova Bridge

The Nova bridge enables us to integrate and render Nova views using any view library like React.

Nova Bridge Diagram

The Nova Bridge emits a NovaMount event to let now to the Nova service that a view needs to be rendered and mounted. The client-side entry point listens to the event and uses the event payload information to render the view. The client-side entry point mounts the rendered view in the Nova Bridge placeholder.

Implementing Nova Bridge

We need to install nova-react-bridge:

$ yarn add nova-react-bridge

Once the package is installed we can place a Nova view inside a React component. We’ll render the Example view on the home page.

The Nova component requires the name and data props

<Nova name="Example" data={{ title: 'Ara Framework' }} />

We need to edit the file src/pages/index.js .

We also need to modify the client-side script in our Nova service to listen to the NovaMount event and mount the view. It’s located in novas/global/src/client.js

The client-side entry point is pretty similar to the server. It uses the name and id from the event to render and mount the view.

Finally, we need to add the entry point script in the html.js file. GatsbyJS uses a default HTML template, so we need copy and override it.

$ cp .cache/default-html.js src/html.js

html.js

We need to run the development server again

$ yarn develop

The Example view shows a heading with the text “Ara Framework”

I know the Example view is so simple, let’s make it more interactive

Example.vue

We added an input control to change the heading text. So let’s go to generate our static website.

Generating static website using GatsbyJS

First, we need to build our GatsbyJS project:

$ yarn build

This command created a folder named public that contains the generated files.

We can use the GatsbyJS CLI to run a server to consume the static files:

$ yarn serve

This command will run the server on http://localhost:9000. Looking at the generated HTML we can notice that GatsbyJS only renders the placeholder, it didn’t render the Nova view.

We need to use Nova Static to include the rendered views by the Nova service.

Include Nova views using Nova Static

Nova Static is a tool part of the Ara Framework that enables us to include Nova views in static HTML files.

Nova Static Diagram

The static site generator generates static files (HTML, CSS, JS, etc). Nova Static reads the HTML files. Nova Static parses and scrapes the HTML to create a request payload for the Nova service (Hypernova Lambda). Nova Static requests the Nova views to the Nova service. The Nova service server-side renders the views and sends them back to Nova Static. Nova Static replace the placeholders with the rendered HTML by the Nova service (Transclusion). Nova Static replaces the content of the HTML file with the new one.

Installing Nova Static

Nova Static is developed using Go, therefore we need to use in our CI/CD a container with GO installed.

We can install the executable:

$ export GOPATH=~/go $ go get github.com/ara-framework/nova-static/nova-static $ go install github.com/ara-framework/nova-static/nova-static $ export PATH="$PATH:$GOPATH/bin"

The executable should be available running the command nova-static , we’ll use it next.

Running Nova Static

First, we need to define some environment variables:

HYPERNOVA_BATCH is the endpoint to requests views to the Nova service.

$ export HYPERNOVA_BATCH=http://localhost:3000/batch

STATIC_FOLDER is the folder that contains the static files

/* Relative path from the gatsby project */

$ export STATIC_FOLDER=./public

Once the environment variables are exported we can run the nova-static command.

$ nova-static

Running the server we can notice the Nova views were included in the static files.

$ yarn serve

The Nova view is also rendered when we disable the JavaScript in the browser. You can use this extension in Chrome.

Another characteristic of Gatsby is the client-side routing. After the page is delivered in the browser the user navigates through the pages without load the page from the static files server.

Let’s add the Example into the page-2 page.

We can notice the Nova views are mounted after navigating to another page as well. Nova Bridge emits the NovaMount event every time a Nova view needs to be mounted. In this case, every time React mounts a Nova component.

Conclusion

Nova services using AWS Lambda are good companions for implementing JAMStack architectures. We can use them to render HTML during build-time and include them into the pages generated by any static site generator (Jekyll, Next, Nuxt, etc).

Nova Bridge gives us the flexibility to integrate Nova views at run-time. In this demo, we mounted VueJS views but we could delivery independent React views that are developed and deployed from other teams.