One of the promises of serverless functions is the ability to bring your own runtime. You can even mix and match runtimes within the same application. In this post, we'll show a reduced example of a serverless side rendered HTML using Deno and a single POST endpoint written with Node.js.
Start with a Deno Hello World example by clicking the button below to deploy a fresh app to Begin.
Behind the scenes, Begin will provision a new GitHub repo and set up your CI/CD all in a single click. Once your app is provisioned clone the repo and install some dependencies.
npm install @architect/functions @begin/data
We'll first modify the app.arc
file. This file is our infrastructure as code manifest. It defines the routes we want to declare as well as where the code for each function.
@app
begin-app
@http
get /
post /pray
@tables
data
scopeID *String
dataID **String
ttl TTL
In our app we have two HTTP functions, a get-index
function and a post-pray
function. We will start with the get-index
function.
// src/http/get-index/index.js
import HTML from "./components/html.js";
import Main from "./components/main.js"
export async function handler(req /*object*/) {
return {
headers: {
"content-type": "text/html; charset=utf8",
},
statusCode: 200,
body: HTML({
title: "SSR in Deno",
children: Main({name: 'Cage'})
}),
};
}
Notice that we're using Deno for this function so we can use import statements. Next, we will create the two components that our app is created with. HTML
is the HTML container code and Main
will be our main app container. These components will have state passed into them from our get-index
function.
// src/http/get-index/components/html.js
export default function document(state={}) {
let {children, title } = state
return `
<!DOCTYPE html>
<html>
<head>
<title>${title}</title>
</head>
<body>
${children}
</body>
</html>
`
}
// src/http/get-index/components/main.js
export default function Main(state={}) {
let { name } = state
let time = new Date().toLocaleTimeString()
return `
<div>
<h1>Praise ${name}</h1>
<p>${time}<p>
<form action='/pray' method="POST">
<input type="text" name="prayer">
<button>Submit</button>
</form>
</div>
`
}
The Main
component is a form element that will POST the input text to our serverless function. So let's take a look at the POST function.
// src/http/post-pray/index.js
const arc = require('@architect/functions')
const data = require('@begin/data')
async function route(req) {
console.log(req.body.prayer)
let save = await data.set({
table: 'prayers',
item: req.body.prayer
})
console.log(save)
return {
location: `/?success=${req.body.prayer}`
}
}
exports.handler = arc.http.async(route)
Our POST function catches the request body and saves it to a DynamoDB table and returns a success query param to illustrate that the server did it's part.
You can view the completed code repo here: https://github.com/pchinjr/deno-mixed-runtimes
Top comments (0)