Build Your First Serverless Website with Alibaba Cloud

What Is Serverless?

Serverless is a new computing paradigm in which you can build applications composed of micro-services running as a response to events. Under this model the services automatically scales according to the usage. This means that you only get charge when they are executed, becoming the most “Pay-As-You-Go” model ever. Of course, this reduces the overall cost of maintenance for your apps, enabling you to more on the logic, deploying faster.

What Will We Build in This Tutorial?

For the purpose of learning, we will keep things simple and clear by setting up a simple “About Me” page. For this, we will leverage Object Storage Service (OSS), API Gateway, Function Compute and Table Store. To make that happen, the idea is to host a static HTML file in an OSS bucket with Public Read Permissions. This page will have a visit counter that will communicate via API Gateway with Function Compute, and keeping the visits count on Table Store. Does it sound complex? Keep reading, you will find it easy.

Let’s Get Started

To start, create a folder for the project. Once inside it, create the file .env for the credentials and leave it there for now.

Install Fun

We said this tutorial will be based on “Fun”. Fun is an official Alibaba Cloud tool to arrange serverless applications resources. Therefore we will use it to deploy our website backend by describing the resources in a template.yml file.

Get Credentials

Well, now that we have all ready to go, let’s get the credentials. Log into the Alibaba Cloud web console and, from the top-right corner, click on AccessKey as shown below:

ACCESS_KEY_SECRET=Replace This with your Access Key Secret
ACCESS_KEY_ID=Replace This with your Access Key
ACCOUNT_ID=Replace This with your Account ID

Create the Template

As we mentioned before, the way Fun works is by reading a YAML file where all the resources are described, all that apart of the specific permissions for the Function Compute Service if needed.

ROSTemplateFormatVersion: '2015-09-01'
Transform: 'Aliyun::Serverless-2018-04-03'
Type: 'Aliyun::Serverless::Service'
Description: 'Function Compute Service for the About Page'
- AliyunOTSFullAccess
Type: 'Aliyun::Serverless::Function'
Handler: visits.handler
Runtime: nodejs8
CodeUri: './'
Timeout: 10
InstanceName: AboutMePageOTS
TableName: visitsTable
Type: 'Aliyun::Serverless::TableStore'
ClusterType: HYBRID
Description: 'Table used to store visits'
Type: 'Aliyun::Serverless::TableStore::Table'
- Name: count_name
Type: 'Aliyun::Serverless::Api'
StageName: RELEASE
x-aliyun-apigateway-api-name: visits_get
arn: acs:fc:::services/${AboutMePage.Arn}/functions/${visits.Arn}/

Create the Function

This is the heart of our project, as it will be the piece of code that will register the visits and retrieve the latest number. The code is using nodejs8 as Runtime and supports the creation of the first value in the table if it doesn’t exist. So, for now, write the following code in a file called visits.js:

const TableStore = require('tablestore')
const Long = TableStore.Long
async function getViewsCount(client) {
const response = await client.getRow({
tableName: process.env['TableName'],
primaryKey: [{ count_name: 'views' }],
maxVersions: 1,
return response.row && response.row.primaryKey
? response.row.attributes[0].columnValue.toNumber()
: null
exports.handler = function (event, context, callback) {
(async () => {
let success = false
let views = null
const client = new TableStore.Client({
accessKeyId: context.credentials.accessKeyId,
secretAccessKey: context.credentials.accessKeySecret,
stsToken: context.credentials.securityToken,
endpoint: `http://${process.env['InstanceName']}.${context.region}`,
instancename: process.env['InstanceName'],
do {
views = await getViewsCount(client) || 0
const tableName = process.env['TableName']
const updateOfAttributeColumns = [{ PUT: [{ count: Long.fromNumber(views + 1) }] }]
const primaryKey = [{ count_name: 'views' }]
const condition = views
? new TableStore.Condition(TableStore.RowExistenceExpectation.IGNORE, new TableStore.SingleColumnCondition('count', Long.fromNumber(views), TableStore.ComparatorType.EQUAL))
: new TableStore.Condition(TableStore.RowExistenceExpectation.EXPECT_NOT_EXIST, null)
try {
await client.updateRow({
success = true
} catch (ex) {
} while (!success)
callback(null, { isBase64Encoded: false, statusCode: 200, body: views })


This step is very straightforward, as Fun includes a command to automatically deploy all the resources defined in the template. For this, we will run fun deploy and wait for the process to finish. It prints a very neat output to inform all what is really happening. From the output we will really need one thing, the API gateway identifier. Somewhere in the last lines, find something like URL: GET, well, copy that URL for later, as we don't need it right now.

Create a Public Bucket

Traditionally, you’ll serve the files using a web server installed in an ECS Instance, said server would interact with the visitor preparing the page contents and sending it back. In this serverless approach, the files will be served from an OSS bucket.

Upload Your Page

Because we need 3 files for this, I prepared a GitHub repository for you to download the files to your local machine and upload them to your bucket. Once you clone it, go to the “oss” folder. The files that need to go to the root folder of your bucket are the ones named index.html, bg.jpg and style.css.



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Alibaba Cloud

Alibaba Cloud

Follow me to keep abreast with the latest technology news, industry insights, and developer trends. Alibaba Cloud website: