基于 Serverless Component 全栈解决方案
什么是 Serverless Component
Serverless Component 是 Serverless Framework 的,支持多个云资源编排和组织的场景化解决方案。
Serverless Component 的目标是磨平不同云服务平台之间差异,你可以将它看作是可以更轻松地构建应用程序的依赖模块。目前 Serverless Component 已经形成一个由社区贡献驱动的生态系统,你可以浏览和使用社区的所有组件,快速开发一款自己想要的应用。

Serverless Component 工作原理
基于 Serverless Component 架构,你可以将任何云服务打包成一个组件。这个组件将含有一份 serverless.yml 配置文件,并且通过简单地进行配置就可以使用。本文以 @serverless/tencent-express 来举例。
如果我们要使用它,只需要新建一个项目 express-demo,然后修改 serverless.yml 配置如下:
express:
component: '@serverless/tencent-express'
inputs:
region: ap-shanghai
因为 serverless 框架部署到云的鉴权都是基于 dotenv 注入全局的变量来实现的,所以还得在根目录下新增 .env 文件,并配置对应的鉴权参数。
之后我们就可以在 app.js 中轻松的编写基于 express 的接口服务了:
const express = require('express')
const app = express()
app.get('/', function(req, res) {
res.send('Hello Express')
})
// 不要忘了导出,因为该组件会对它进行包装,输出成云函数
module.exports = app
这背后所有的流程逻辑都是组件内部实现的,包括:云函数的部署,API 网关的生成等。
下面是一张简单的组件依赖图:

通过此图可以清晰地查看组件带来的收益,借助社区现有的 @serverless/tencent-express 和 @serverless/tencent-website 组件,我们就可以很快构建想要的全栈应用。
全栈应用实战
接下来将介绍如何借助 Serverless Component 快速开发全栈 Web 应用。

在开始所有步骤前,需执行
npm install -g serverless命令,全局安装serverless cli。
准备
新建项目目录 fullstack-application-vue,在该项目目录下新增 api 和 dashboard 目录。然后新增 serverless.yml 和 .env 配置文件,项目目录结构如下:
├── README.md // 项目说明文档
├── api // Restful api 后端服务
├── dashboard // 前端页面
├── .env // 腾讯云相关鉴权参数:TENCENT_APP_ID,TENCENT_SECRET_ID,TENCENT_SECRET_KEY
└── serverless.yml // serverless 文件
后端服务开发
进入目录 api,新增 app.js 文件,编写 express 服务代码,这里先新增一个路由 /,并返回当前服务器时间:
const express = require('express')
const cors = require('cors')
const app = express()
app.use(cors())
app.get('/', (req, res) => {
res.send(JSON.stringfy({ message: `Server time: ${new Date().toString()}` }))
})
module.exports = app
前端页面开发
本案例使用的是 Vue.js + Parcel 的前端模板,当然你可以使用任何前端项目脚手架,比如 Vue.js 官方推荐的 Vue CLI 生成的项目。进入 dashboard 目录,静态资源你可以直接复制我准备好的 项目模板,编写入口文件 src/index.js:
// 这里初始是没有 env.js 模块的,第一次部署后会自动生成
require('../env')
const Vue = require('vue')
module.exports = new Vue({
el: '#root',
data: {
message: 'Click me!',
isVisible: true,
},
methods: {
async queryServer() {
const response = await fetch(window.env.apiUrl)
const result = await response.json()
this.message = result.message
},
},
})
配置
前后端代码都准备好了,现在我们还需要简单配置下 serverless.yml 文件了:
name: fullstack-application-vue
frontend:
component: '@serverless/tencent-website'
# inputs 为 @serverless/tencent-website 组件的输入
# 具体配置说明参考:https://github.com/serverless-components/tencent-website/blob/master/docs/configure.md
inputs:
code:
src: dist
root: frontend
hook: npm run build
env:
# 下面的 API服务部署后,获取对应的 api 请求路径
apiUrl: ${api.url}
api:
component: '@serverless/tencent-express'
# inputs 为 @serverless/tencent-express 组件的输入
# 具体配置说明参考:https://github.com/serverless-components/tencent-express/blob/master/docs/configure.md
inputs:
code: ./api
functionName: fullstack-vue-api
apigatewayConf:
protocol: https
简单的介绍下配置:首先,该文件定义了
frontend和api两个模块,分别通过component属性指定依赖的 Serverless Component。对于一个标准的 Serverless Component,都会接受一个inputs属性参数,然后组件会根据inputs的配置进行处理和部署,具体有关配置的参数说明,请参考相关组件的官方配置说明。
部署
以上所有的步骤都完成后,接下来就是第一次部署了。
为什么不是直接联调开发呢?因为后端服务是云函数,但是到目前为止,所有代码都是在本地编写,前端页面接口请求链接还不存在。所以需要先将云函数部署到云端,才能进行前后端调试。这个也是本人目前遇到的痛点,因为每次修改后端服务后,都需要重新部署,然后进行前端开发调试。如果你有更好的建议,欢迎评论指教~
部署时,只需要运行 serverless 命令就行,当然如果你需要查看部署中的 DEBUG 信息,还需要加上 --debug 参数,如下:
$ serverless
# or
$ serverless --debug
然后终端会 balabalabala~, 输出一大堆 DEBUG 信息,最后只需要看到绿色的 done 就行了:

这样一个基于 Serverless Component 的全栈应用就开发好了。赶紧点击你部署好的链接体验一下吧~
数据库连接
既然是全栈,怎么少得了数据库的读写呢?接下来介绍如何添加数据库的读写操作。
准备
想要操作数据库,必须先拥有一台数据库实例,腾讯云 MySQL 云数据库 现在也很便宜,可以购买一个最基本按量计费 1 核 1G 内存 的 1 小时收费不到 4 毛钱,是不是非常划算。购买好之后初始化配置,然后新增一个 serverless 数据库,同时新增一张 users 表:
CREATE TABLE if not exists `test` ( `name` varchar (32) NOT NULL ,`email` varchar (64) NOT NULL ,`site` varchar (128) NOT NULL ) ENGINE = innodb DEFAULT CHARACTER SET = "utf8mb4" COLLATE = "utf8mb4_general_ci"
前端修改
首先修改前端入口文件 frontend/src/index.js 新增相关函数操作:
require('../env')
const Vue = require('vue')
const axios = require('axios')
module.exports = new Vue({
el: '#root',
data: {
// ...
form: {
name: '',
email: '',
site: '',
},
userList: [],
},
methods: {
// ...
// 获取用户列表
async getUsers() {
const res = await axios.get(window.env.apiUrl + 'users')
this.userList = (res.data && res.data.data) || []
},
// 新增一个用户
async addUser() {
const data = this.form
const res = await axios.post(window.env.apiUrl + 'users', data)
console.log(res)
if (res.data) {
this.getUsers()
}
},
},
mounted() {
// 视图挂在后,获取用户列表
this.getUsers()
},
})
当然你还需要修改视图模板文件 frontend/index.html,在页面模板中新增用户列表和用户表单:
<!-- user form -->
<section class="user-form" action="#">
<div class="form-item">
<label for="name">
Name:
</label>
<input name="name" v-model="form.name" type="text" /><br />
</div>
<div class="form-item">
<label for="email">
Email:
</label>
<input name="email" v-model="form.email" type="email" /><br />
</div>
<div class="form-item">
<label for="site">
Site:
</label>
<input name="site" v-model="form.site" type="text" /><br />
</div>
<button @click="addUser">Submit</button>
</section>
<!-- user list -->
<section class="user-list">
<ul v-if="userList.length > 0">
<li v-for="item in userList" :key="item.id">
<p>
<b>Name: {{ item.name }}</b>
<b>Email: {{ item.email }}</b>
<b>Site: {{ item.site }}</b>
</p>
</li>
</ul>
<span v-else>No Data</span>
</section>
注意:如果还不熟悉 Vue.js 语法,请移至 官方文档,当然如果你想快速上手 Vue.js 开发,也可以阅读这份 Vue 从入门到精通 教程。
后端修改
这里使用 .env 来进行数据库连接参数配置,在 api 目录下新增 .env 文件,将之前的数据库配置填入文件中,参考 api/.env.example 文件。然后添加并安装 dotenv 依赖,同时添加 mysql2 模块进行数据库操作,body-parser 模块进行 POST 请求时的 body 解析。
之后新增后端 api,进行数据库读写,修改后的 api/app.js 代码如下:
'use strict'
require('dotenv').config()
const express = require('express')
const cors = require('cors')
const mysql = require('mysql2')
const bodyParser = require('body-parser')
// init mysql connection
function initMysqlPool() {
const { DB_HOST, DB_PORT, DB_DATABASE, DB_USER, DB_PASSWORD } = process.env
const promisePool = mysql
.createPool({
host: DB_HOST,
user: DB_USER,
port: DB_PORT,
password: DB_PASSWORD,
database: DB_DATABASE,
connectionLimit: 1,
})
.promise()
return promisePool
}
const app = express()
app.use(bodyParser.json())
app.use(cors())
if (!app.promisePool) {
app.promisePool = initMysqlPool()
}
app.get('/', (req, res) => {
res.send(JSON.stringify({ message: `Server time: ${new Date().toString()}` }))
})
// get user list
app.get('/users', async (req, res) => {
const [data] = await app.promisePool.query('select * from users')
res.send(
JSON.stringify({
data: data,
})
)
})
// add new user
app.post('/users', async (req, res) => {
let result = ''
try {
const { name, email, site } = req.body
const [res] = await app.promisePool.query('INSERT into users SET ?', {
name: name,
email: email,
site: site,
})
result = {
data: res && res.insertId,
message: 'Insert Success',
}
} catch (e) {
result = {
data: e,
message: 'Insert Fail',
}
}
res.send(JSON.stringify(result))
})
module.exports = app
配置修改
这里数据库访问需要通过腾讯云私有网络,所以还需要为云函数配置私有网络(VPC),同时还需要配置能够操作数据库的角色(关于角色配置,可以直接到 角色管理页面),这里我新建了一个 QCS_SCFFull 的角色,可以用来访问数据库。然后修改 serverless.yml 中的配置:
# ...
api:
component: '@serverless/tencent-express'
# more configuration for @serverless/tencent-website,
# refer to: https://github.com/serverless-components/tencent-express/blob/master/docs/configure.md
inputs:
code: ./api
functionName: fullstack-vue-api
role: QCS_SCFFull # 此角色必须具备访问数据库权限
functionConf:
# 这个是用来访问新创建数据库的私有网络,可以在你的数据库实例管理页面查看
vpcConfig:
vpcId: vpc-6n5x55kb
subnetId: subnet-4cvr91js
apigatewayConf:
protocol: https
最后重新部署一下就行了。
以上基于腾讯云 Serverless Framework 来实现:
小结
当然全栈方案,并没有这么简单,这里只是简单介绍,如何使用 Serverless Component,快速实现一个全栈应用。如果要应用到实际的业务场景,我们还需考虑更多的问题,期待大家去探索和发现!
传送门:
- GitHub: github.com/serverless
- 官网:serverless.com
欢迎访问:Serverless 中文网,您可以在 最佳实践 里体验更多关于 Serverless 应用的开发!
基于 Serverless Component 全栈解决方案的更多相关文章
- 基于 Serverless Component 全栈解决方案 Ⅱ
虽然之前的文章 基于 Serverless Component 的全栈解决方案 介绍了如何借助 Serverless Component 快速搭建 Restful API 后端服务 和 Vue.js ...
- 基于NodeJS的全栈式开发
前言 为了解决传统Web开发模式带来的各种问题,我们进行了许多尝试,但由于前/后端的物理鸿沟,尝试的方案都大同小异.痛定思痛,今天我们重新思考了“前后端”的定义,引入前端同学都熟悉的 NodeJS,试 ...
- (转)也谈基于NodeJS的全栈式开发(基于NodeJS的前后端分离)
原文链接:http://ued.taobao.org/blog/2014/04/full-stack-development-with-nodejs/ 随着不同终端(pad/mobile/pc)的兴起 ...
- 也谈基于NodeJS的全栈式开发(基于NodeJS的前后端分离)
前言 为了解决传统Web开发模式带来的各种问题,我们进行了许多尝试,但由于前/后端的物理鸿沟,尝试的方案都大同小异.痛定思痛,今天我们重新思考了“前后端”的定义,引入前端同学都熟悉的NodeJS,试图 ...
- 基于NodeJS的全栈式开发(基于NodeJS的前后端分离)
也谈基于NodeJS的全栈式开发(基于NodeJS的前后端分离) 前言 为了解决传统Web开发模式带来的各种问题,我们进行了许多尝试,但由于前/后端的物理鸿沟,尝试的方案都大同小异.痛定思痛,今天我们 ...
- 从React Native到微服务,落地一个全栈解决方案
Poplar是一个社交主题的内容社区,但自身并不做社区,旨在提供可快速二次开发的开源基础套件.前端基于React Native与Redux构建,后端由Spring Boot.Dubbo.Zookeep ...
- Serverless Component 介绍和使用指南
Serverless Component 是什么,我怎样使用它? Serverless Components 的目标是什么? 我们希望通过 Serverless Components 让广大开发者更加 ...
- FKP,一套全栈框架,基于react、webpack、koa1、babel
FKP-REST是一套前后端分离,基于javascript的全栈实现,基于node的高性能,易部署性及javascript前后端语言的一致性,学习成本,时间成本及项目快速启动等等方面,FKP都是一种不 ...
- [cnBeta]阿里云推出全栈IPv6解决方案 加速推进下一代互联网应用
https://www.cnbeta.com/articles/tech/795695.htm 访问: 阿里云 - 最高1888元通用代金券立即可用 作为国内首个全面支持IPv6的云厂商,过去5个月, ...
随机推荐
- 菜鸟学习Fabric源码学习 — 背书节点和链码容器交互
Fabric 1.4 源码分析 背书节点和链码容器交互 本文档主要介绍背书节点和链码容器交互流程,在Endorser背书节点章节中,无论是deploy.upgrade或者调用链码,最后都会调用Chai ...
- 如何修改Docker已运行实例的端口映射
如何修改Docker已运行实例的端口映射 Docker的端口映射,往往出现在两个阶段需要处理: 1.是在docker启动前就已经确定好,哪个docker实例映射哪个端口(往往这个情况比较,需要提前做规 ...
- Win10系统下MySQL压缩版安装配置教程
MySQL分为安装版和压缩.为了以后MySQL出问题想重装时的各种不必要的麻烦,我个人推荐压缩版MySQL.下面进入教程: 进入官网下载MySQL压缩包,并解压如下 配置环境变量---将bin文件的目 ...
- C语言之指针用法总结
C语言指针概述:1.计算机系统中,无论是存入或是取出数据都需要与内存单元打交道,物理器件通过地址编码寻找内存单元.2.地址编码是一种数据,C语言的指针类型正是为了表示这种计算机所特有的地址数据.3.存 ...
- 最短路变形题目 HDU多校7
Mr.Quin love fishes so much and Mr.Quin’s city has a nautical system,consisiting of N ports and M sh ...
- Java入门 - 高级教程 - 08.Applet
原文地址:http://www.work100.net/training/java-applet.html 更多教程:光束云 - 免费课程 Applet 序号 文内章节 视频 1 概述 2 Apple ...
- 异数OS TCP协议栈测试(一)--数据传输篇
异数OS TCP协议栈测试(一)--数据传输篇 本文来自异数OS社区 github: 异数OS-织梦师(消息中间件)群: 476260389 测试目标 数据传输IO性能测试,主要是建立连接后测试收 ...
- 图像矫正技术深入探讨(opencv)
刚进入实验室导师就交给我一个任务,就是让我设计算法给图像进行矫正.哎呀,我不太会图像这块啊,不过还是接下来了,硬着头皮开干吧! 那什么是图像的矫正呢?举个例子就好明白了. 我的好朋友小明给我拍了这几张 ...
- Java基础系列1:深入理解Java数据类型
Java基础系列1:深入理解Java数据类型 当初学习计算机的时候,教科书中对程序的定义是:程序=数据结构+算法,Java基础系列第一篇就聊聊Java中的数据类型. 本篇聊Java数据类型主要包括四个 ...
- Mesh R-CNN 论文翻译(原理部分)
毕设做Mesh R-CNN的实现,在此翻译一下原论文.原论文https://arxiv.org/pdf/1906.02739.pdf. 摘要 二维感知的快速发展使得系统能够准确地检测真实世界图像中的物 ...