本文將介紹如何基於 Egg.js 和 Serverless 實現一個后台管理系統
作為一名前端開發者,在選擇 Nodejs 后端服務框架時,第一時間會想到 Egg.js,不得不說 Egg.js
是一個非常優秀的企業級框架,它的高擴展性和豐富的插件,極大的提高了開發效率。開發者只需要關注業務就好,比如要使用 redis
,引入 egg-redis 插件,然后簡單配置就可以了。正因為如此,第一次接觸它,我便喜歡上了它,之后也用它開發過不少應用。
有了如此優秀的框架,那么如何將一個 Egg.js
的服務遷移到 Serverless
架構上呢?
背景
我在文章 基於 Serverless Component 的全棧解決方案 中講述了,如何將一個基於 Vue.js
的前端應用和基於 Express
的后端服務,快速部署到騰訊雲上。雖然受到不少開發者的喜愛,但是很多開發者私信問我,這還是一個 Demo
性質的項目而已,有沒有更加實用性的解決方案。而且他們實際開發中,很多使用的正是 Egg.js
框架,能不能提供一個 Egg.js
的解決方案?
本文將手把手教你結合 Egg.js
和 Serverless
實現一個后台管理系統。
讀完此文你將學到:
- Egg.js 基本使用
- 如何使用 Sequelize ORM 模塊進行 Mysql 操作
- 如何使用 Redis
- 如何使用 JWT 進行用戶登錄驗證
- Serverless Framework 的基本使用
- 如何將本地開發好的 Egg.js 應用部署到騰訊雲雲函數上
- 如何基於雲端對象存儲快速部署靜態網站
Egg.js 入門
初始化 Egg.js 項目:
$ mkdir egg-example && cd egg-example
$ npm init egg --type=simple
$ npm i
啟動項目:
$ npm run dev
然后瀏覽器訪問 http://localhost:7001
,就可以看到親切的 hi, egg
了。
關於 Egg.js 的框架更多知識,建議閱讀 官方文檔
准備
對 Egg.js 有了簡單了解,接下來我們來初始化我們的后台管理系統,新建一個項目目錄 admin-system
:
$ mkdir admin-system
將上面創建的 Egg.js 項目復制到 admin-system
目錄下,重命名為 backend
。然后將前端模板項目復制到 frontend
文件夾中:
$ git clone https://github.com/PanJiaChen/vue-admin-template.git frontend
說明: vue-admin-template 是基於 Vue2.0 的管理系統模板,是一個非常優秀的項目,建議對 Vue.js 感興趣的開發者可以去學習下,當然如果你對 Vue.js 還不是太了解,這里有個基礎入門學習教程 Vuejs 從入門到精通系列文章
之后你的項目目錄結構如下:
.
├── README.md
├── backend // 創建的 Egg.js 項目
└── frontend // 克隆的 Vue.js 前端項目模板
啟動前端項目熟悉下界面:
$ cd frontend
$ npm install
$ npm run dev
然后訪問 http://localhost:9528
就可以看到登錄界面了。
開發后端服務
對於一個后台管理系統服務,我們這里只實現登錄鑒權和文章管理功能,剩下的其他功能大同小異,讀者可以之后自由補充擴展。
1. 添加 Sequelize 插件
在正式開發之前,我們需要引入數據庫插件,這里本人偏向於使用 Sequelize ORM 工具進行數據庫操作,正好 Egg.js 提供了 egg-sequelize 插件,於是直接拿來用,需要先安裝:
$ cd frontend
# 因為需要通過 sequelize 鏈接 mysql 所以這也同時安裝 mysql2 模塊
$ npm install egg-sequelize mysql2 --save
然后在 backend/config/plugin.js
中引入該插件:
module.exports = {
// ....
sequelize: {
enable: true,
package: "egg-sequelize"
}
// ....
};
在 backend/config/config.default.js
中配置數據庫連接參數:
// ...
const userConfig = {
// ...
sequelize: {
dialect: "mysql",
// 這里也可以通過 .env 文件注入環境變量,然后通過 process.env 獲取
host: "xxx",
port: "xxx",
database: "xxx",
username: "xxx",
password: "xxx"
}
// ...
};
// ...
2. 添加 JWT 插件
系統將使用 JWT token 方式進行登錄鑒權,安裝配置參考官方文檔,egg-jwt
3. 添加 Redis 插件
系統將使用 redis 來存儲和管理用戶 token,安裝配置參考官方文檔,egg-redis
4. 角色 API
定義用戶模型,創建 backend/app/model/role.js
文件如下:
module.exports = app => {
const { STRING, INTEGER, DATE } = app.Sequelize;
const Role = app.model.define("role", {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
name: STRING(30),
created_at: DATE,
updated_at: DATE
});
// 這里定義與 users 表的關系,一個角色可以含有多個用戶,外鍵相關
Role.associate = () => {
app.model.Role.hasMany(app.model.User, { as: "users" });
};
return Role;
};
實現 Role 相關服務,創建 backend/app/service/role.js
文件如下:
const { Service } = require("egg");
class RoleService extends Service {
// 獲取角色列表
async list(options) {
const {
ctx: { model }
} = this;
return model.Role.findAndCountAll({
...options,
order: [
["created_at", "desc"],
["id", "desc"]
]
});
}
// 通過 id 獲取角色
async find(id) {
const {
ctx: { model }
} = this;
const role = await model.Role.findByPk(id);
if (!role) {
this.ctx.throw(404, "role not found");
}
return role;
}
// 創建角色
async create(role) {
const {
ctx: { model }
} = this;
return model.Role.create(role);
}
// 更新角色
async update({ id, updates }) {
const role = await this.ctx.model.Role.findByPk(id);
if (!role) {
this.ctx.throw(404, "role not found");
}
return role.update(updates);
}
// 刪除角色
async destroy(id) {
const role = await this.ctx.model.Role.findByPk(id);
if (!role) {
this.ctx.throw(404, "role not found");
}
return role.destroy();
}
}
module.exports = RoleService;
一個完整的 RESTful API 就該包括以上五個方法,然后實現 RoleController
, 創建 backend/app/controller/role.js
:
const { Controller } = require("egg");
class RoleController extends Controller {
async index() {
const { ctx } = this;
const { query, service, helper } = ctx;
const options = {
limit: helper.parseInt(query.limit),
offset: helper.parseInt(query.offset)
};
const data = await service.role.list(options);
ctx.body = {
code: 0,
data: {
count: data.count,
items: data.rows
}
};
}
async show() {
const { ctx } = this;
const { params, service, helper } = ctx;
const id = helper.parseInt(params.id);
ctx.body = await service.role.find(id);
}
async create() {
const { ctx } = this;
const { service } = ctx;
const body = ctx.request.body;
const role = await service.role.create(body);
ctx.status = 201;
ctx.body = role;
}
async update() {
const { ctx } = this;
const { params, service, helper } = ctx;
const body = ctx.request.body;
const id = helper.parseInt(params.id);
ctx.body = await service.role.update({
id,
updates: body
});
}
async destroy() {
const { ctx } = this;
const { params, service, helper } = ctx;
const id = helper.parseInt(params.id);
await service.role.destroy(id);
ctx.status = 200;
}
}
module.exports = RoleController;
之后在 backend/app/route.js
路由配置文件中定義 role
的 RESTful API:
router.resources("roles", "/roles", controller.role);
通過 router.resources
方法,我們將 roles
這個資源的增刪改查接口映射到了 app/controller/roles.js
文件。詳細說明參考 官方文檔
5. 用戶 API
同 Role 一樣定義我們的用戶 API,這里就不復制粘貼了,可以參考項目實例源碼 admin-system。
6. 同步數據庫表格
上面只是定義好了 Role
和 User
兩個 Schema,那么如何同步到數據庫呢?這里先借助 Egg.js 啟動的 hooks 來實現,Egg.js 框架提供了統一的入口文件(app.js)進行啟動過程自定義,這個文件返回一個 Boot 類,我們可以通過定義 Boot 類中的生命周期方法來執行啟動應用過程中的初始化工作。
我們在 backend
目錄中創建 app.js
文件,如下:
"use strict";
class AppBootHook {
constructor(app) {
this.app = app;
}
async willReady() {
// 這里只能在開發模式下同步數據庫表格
const isDev = process.env.NODE_ENV === "development";
if (isDev) {
try {
console.log("Start syncing database models...");
await this.app.model.sync({ logging: console.log, force: isDev });
console.log("Start init database data...");
await this.app.model.query(
"INSERT INTO roles (id, name, created_at, updated_at) VALUES (1, 'admin', '2020-02-04 09:54:25', '2020-02-04 09:54:25'),(2, 'editor', '2020-02-04 09:54:30', '2020-02-04 09:54:30');"
);
await this.app.model.query(
"INSERT INTO users (id, name, password, age, avatar, introduction, created_at, updated_at, role_id) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 20, 'https://yugasun.com/static/avatar.jpg', 'Fullstack Engineer', '2020-02-04 09:55:23', '2020-02-04 09:55:23', 1);"
);
await this.app.model.query(
"INSERT INTO posts (id, title, content, created_at, updated_at, user_id) VALUES (2, 'Awesome Egg.js', 'Egg.js is a awesome framework', '2020-02-04 09:57:24', '2020-02-04 09:57:24', 1),(3, 'Awesome Serverless', 'Build web, mobile and IoT applications using Tencent Cloud and API Gateway, Tencent Cloud Functions, and more.', '2020-02-04 10:00:23', '2020-02-04 10:00:23', 1);"
);
console.log("Successfully init database data.");
console.log("Successfully sync database models.");
} catch (e) {
console.log(e);
throw new Error("Database migration failed.");
}
}
}
}
module.exports = AppBootHook;
通過 willReady
生命周期函數,我們可以執行 this.app.model.sync()
函數來同步數據表,當然這里同時初始化了角色和用戶數據記錄,用來做為演示用。
注意:這的數據庫同步只是本地調試用,如果想要騰訊雲的 Mysql 數據庫,建議開啟遠程連接,通過
sequelize db:migrate
實現,而不是每次啟動 Egg 應用時同步,示例代碼已經完成此功能,參考 Egg Sequelize 文檔。
這里本人為了省事,直接開啟騰訊雲 Mysql 公網連接,然后修改config.default.js
中的sequelize
配置,運行npm run dev
進行開發模式同步。
到這里,我們的用戶和角色的 API 都已經定義好了,啟動服務 npm run dev
,訪問 https://127.0.0.1:7001/users
可以獲取所有用戶列表了。
7. 用戶登錄/注銷 API
這里登錄邏輯比較簡單,客戶端發送 用戶名
和 密碼
到 /login
路由,后端通過 login
函數接受,然后從數據庫中查詢該用戶名,同時比對密碼是否正確。如果正確則調用 app.jwt.sign()
函數生成 token
,並將 token
存入到 redis
中,同時返回該 token
,之后客戶端需要鑒權的請求都會攜帶 token
,進行鑒權驗證。思路很簡單,我們就開始實現了。
流程圖如下:

首先,在 backend/app/controller/home.js
中新增登錄處理 login
方法:
class HomeController extends Controller {
// ...
async login() {
const { ctx, app, config } = this;
const { service, helper } = ctx;
const { username, password } = ctx.request.body;
const user = await service.user.findByName(username);
if (!user) {
ctx.status = 403;
ctx.body = {
code: 403,
message: "Username or password wrong"
};
} else {
if (user.password === helper.encryptPwd(password)) {
ctx.status = 200;
const token = app.jwt.sign(
{
id: user.id,
name: user.name,
role: user.role.name,
avatar: user.avatar
},
config.jwt.secret,
{
expiresIn: "1h"
}
);
try {
await app.redis.set(`token_${user.id}`, token);
ctx.body = {
code: 0,
message: "Get token success",
token
};
} catch (e) {
console.error(e);
ctx.body = {
code: 500,
message: "Server busy, please try again"
};
}
} else {
ctx.status = 403;
ctx.body = {
code: 403,
message: "Username or password wrong"
};
}
}
}
}
注釋:這里有個密碼存儲邏輯,用戶在注冊時,密碼都是通過
helper
函數encryptPwd()
進行加密的(這里用到最簡單的 md5 加密方式,實際開發中建議使用更加高級加密方式),所以在校驗密碼正確性時,也需要先加密一次。至於如何在 Egg.js 框架中新增helper
函數,只需要在backend/app/extend
文件夾中新增helper.js
文件,然后modole.exports
一個包含該函數的對象就行,參考 Egg 框架擴展文檔
然后,在 backend/app/controller/home.js
中新增 userInfo
方法,獲取用戶信息:
async userInfo() {
const { ctx } = this;
const { user } = ctx.state;
ctx.status = 200;
ctx.body = {
code: 0,
data: user,
};
}
egg-jwt 插件,在鑒權通過的路由對應 controller 函數中,會將 app.jwt.sign(user, secrete)
加密的用戶信息,添加到 ctx.state.user
中,所以 userInfo
函數只需要將它返回就行。
之后,在 backend/app/controller/home.js
中新增 logout
方法:
async logout() {
const { ctx } = this;
ctx.status = 200;
ctx.body = {
code: 0,
message: 'Logout success',
};
}
userInfo
和 logout
函數非常簡單,重點是路由中間件如何處理。
接下來,我們來定義登錄相關路由,修改 backend/app/router.js
文件,新增 /login
, /user-info
, /logout
三個路由:
const koajwt = require("koa-jwt2");
module.exports = app => {
const { router, controller, jwt } = app;
router.get("/", controller.home.index);
router.post("/login", controller.home.login);
router.get("/user-info", jwt, controller.home.userInfo);
const isRevokedAsync = function(req, payload) {
return new Promise(resolve => {
try {
const userId = payload.id;
const tokenKey = `token_${userId}`;
const token = app.redis.get(tokenKey);
if (token) {
app.redis.del(tokenKey);
}
resolve(false);
} catch (e) {
resolve(true);
}
});
};
router.post(
"/logout",
koajwt({
secret: app.config.jwt.secret,
credentialsRequired: false,
isRevoked: isRevokedAsync
}),
controller.home.logout
);
router.resources("roles", "/roles", controller.role);
router.resources("users", "/users", controller.user);
router.resources("posts", "/posts", controller.post);
};
Egg.js 框架定義路由時,router.post()
函數可以接受中間件函數,用來處理一些路由相關的特殊邏輯。
比如 /user-info
,路由添加了 app.jwt
作為 JWT 鑒權中間件函數,至於為什么這么用,egg-jwt 插件有明確說明。
這里稍微復雜的是 /logout
路由,因為我們在注銷登錄時,需要將用戶的 token
從 redis
中移除,所以這里借助了 koa-jwt2 的 isRevokded
參數,來進行 token
刪除。
后端服務部署
到這里,后端服務的登錄和注銷邏輯基本完成了。那么如何部署到雲函數呢?可以直接使用 tencent-egg 組件,它是專門為 Egg.js 框架打造的 Serverless Component,使用它可以快速將我們的 Egg.js 項目部署到騰訊雲雲函數上。
1. 准備
我們先創建一個 backend/sls.js
入口文件:
const { Application } = require("egg");
const app = new Application();
module.exports = app;
然后修改 backend/config/config.default.js
文件:
const config = (exports = {
env: "prod", // 推薦雲函數的 egg 運行環境變量修改為 prod
rundir: "/tmp",
logger: {
dir: "/tmp"
}
});
注釋:這里之所有需要修改運行和日志目錄,是因為雲函數運行時,只有
/tmp
才有寫權限。
全局安裝 serverless
命令:
$ npm install serverless -g
2. 配置 Serverless
在項目根目錄下創建 serverless.yml
文件,同時新增 backend
配置:
backend:
component: "@serverless/tencent-egg"
inputs:
code: ./backend
functionName: admin-system
# 這里必須指定一個具有操作 mysql 和 redis 的角色,具體角色創建,可訪問 https://console.cloud.tencent.com/cam/role
role: QCS_SCFFull
functionConf:
timeout: 120
# 這里的私有網絡必須和 mysql、redis 實例一致
vpcConfig:
vpcId: vpc-xxx
subnetId: subnet-xxx
apigatewayConf:
protocols:
- https
此時你的項目目錄結構如下:
.
├── README.md // 項目說明文件
├── serverless.yml // serverless yml 配合文件
├── backend // 創建的 Egg.js 項目
└── frontend // 克隆的 Vue.js 前端項目模板
3. 執行部署
執行部署命令:
$ serverless --debug
之后控制台需要進行掃碼登錄驗證騰訊雲賬號,掃碼登錄就好。等部署成功會發揮如下信息:
backend:
region: ap-guangzhou
functionName: admin-system
apiGatewayServiceId: service-f1bhmhk4
url: https://service-f1bhmhk4-1251556596.gz.apigw.tencentcs.com/release/
這里輸出的 url 就是部署成功的 API 網關接口,可以直接訪問測試。
注釋:雲函數部署時,會自動在騰訊雲的 API 網關創建一個服務,同時創建一個 API,通過該 API 就可以觸發雲函數執行了。
4. 賬號配置(可選)
當前默認支持 Serverless cli 掃描二維碼登錄,如果希望配置持久的環境變量/秘鑰信息,也可以在項目根目錄創建 .env
文件
在 .env
文件中配置騰訊雲的 SecretId 和 SecretKey 信息並保存,密鑰可以在 API 密鑰管理 中獲取或者創建.
# .env
TENCENT_SECRET_ID=123
TENCENT_SECRET_KEY=123
5. 文章 API
跟用戶 API 類似,只需要復制粘貼上面用戶相關模塊,修改名稱為 posts
, 並修改數據模型就行,這里就不粘貼代碼了。
前端開發
本實例直接使用的 vue-admin-template 的前端模板。
我們需要做如下幾部分修改:
- 刪除接口模擬:更換為真實的后端服務接口
- 修改接口函數:包括用戶相關的
frontend/src/api/user.js
和文章相關接口frontend/src/api/post.js
。 - 修改接口工具函數:主要是修改
frontend/src/utils/request.js
文件,包括axios
請求的baseURL
和請求的 header。 - UI 界面修改:主要是新增文章管理頁面,包括列表頁和新增頁。
1. 刪除接口模擬
首先刪除 frontend/mock
文件夾。然后修改前端入口文件 frontend/src/main.js
:
// 1. 引入接口變量文件,這個會依賴 @serverless/tencent-website 組件自動生成
import "./env.js";
import Vue from "vue";
import "normalize.css/normalize.css";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
import locale from "element-ui/lib/locale/lang/en";
import "@/styles/index.scss";
import App from "./App";
import store from "./store";
import router from "./router";
import "@/icons";
import "@/permission";
// 2. 下面這段就是 mock server 引入,刪除就好
// if (process.env.NODE_ENV === 'production') {
// const { mockXHR } = require('../mock')
// mockXHR()
// }
Vue.use(ElementUI, { locale });
Vue.config.productionTip = false;
new Vue({
el: "#app",
router,
store,
render: h => h(App)
});
2. 修改接口函數
修改 frontend/src/api/user.js
文件,包括登錄、注銷、獲取用戶信息和獲取用戶列表函數如下:
import request from "@/utils/request";
// 登錄
export function login(data) {
return request({
url: "/login",
method: "post",
data
});
}
// 獲取用戶信息
export function getInfo(token) {
return request({
url: "/user-info",
method: "get"
});
}
// 注銷登錄
export function logout() {
return request({
url: "/logout",
method: "post"
});
}
// 獲取用戶列表
export function getList() {
return request({
url: "/users",
method: "get"
});
}
新增 frontend/src/api/post.js
文件如下:
import request from "@/utils/request";
// 獲取文章列表
export function getList(params) {
return request({
url: "/posts",
method: "get",
params
});
}
// 創建文章
export function create(data) {
return request({
url: "/posts",
method: "post",
data
});
}
// 刪除文章
export function destroy(id) {
return request({
url: `/posts/${id}`,
method: "delete"
});
}
3. 修改接口工具函數
因為 @serverless/tencent-website
組件可以定義 env
參數,執行成功后它會在指定 root
目錄自動生成 env.js
,然后在 frontend/src/main.js
中引入使用。
它會掛載 env
中定義的接口變量到 window
對象上。比如這生成的 env.js
文件如下:
window.env = {};
window.env.apiUrl =
"https://service-f1bhmhk4-1251556596.gz.apigw.tencentcs.com/release/";
根據此文件我們來修改 frontend/src/utils/request.js
文件:
import axios from "axios";
import { MessageBox, Message } from "element-ui";
import store from "@/store";
import { getToken } from "@/utils/auth";
// 創建 axios 實例
const service = axios.create({
// 1. 這里設置為 `env.js` 中的變量 `window.env.apiUrl`
baseURL: window.env.apiUrl || "/", // url = base url + request url
timeout: 5000 // request timeout
});
// request 注入
service.interceptors.request.use(
config => {
// 2. 添加鑒權token
if (store.getters.token) {
config.headers["Authorization"] = `Bearer ${getToken()}`;
}
return config;
},
error => {
console.log(error); // for debug
return Promise.reject(error);
}
);
// 請求 response 注入
service.interceptors.response.use(
response => {
const res = response.data;
// 只有請求code為0,才是正常返回,否則需要提示接口錯誤
if (res.code !== 0) {
Message({
message: res.message || "Error",
type: "error",
duration: 5 * 1000
});
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// to re-login
MessageBox.confirm(
"You have been logged out, you can cancel to stay on this page, or log in again",
"Confirm logout",
{
confirmButtonText: "Re-Login",
cancelButtonText: "Cancel",
type: "warning"
}
).then(() => {
store.dispatch("user/resetToken").then(() => {
location.reload();
});
});
}
return Promise.reject(new Error(res.message || "Error"));
} else {
return res;
}
},
error => {
console.log("err" + error);
Message({
message: error.message,
type: "error",
duration: 5 * 1000
});
return Promise.reject(error);
}
);
export default service;
4. UI 界面修改
關於 UI 界面修改,這里就不做說明了,因為涉及到 Vue.js 的基礎使用,如果還不會使用 Vue.js,建議先復制示例代碼就好。如果對 Vue.js 感興趣,可以到 Vue.js 官網 學習。也可以閱讀本人的 Vuejs 從入門到精通系列文章,喜歡的話,可以送上您寶貴的 Star (*^▽^*)
這里只需要復制 Demo 源碼 的 frontend/router
和 frontend/views
兩個文件夾就好。
前端部署
因為前端編譯后都是靜態文件,我們需要將靜態文件上傳到騰訊雲的 COS(對象存儲) 服務,然后開啟 COS 的靜態網站功能就可以了,這些都不需要你手動操作,使用 @serverless/tencent-website 組件就可以輕松搞定。
1. 修改 Serverless 配置文件
修改項目根目錄下 serverless.yml
文件,新增前端相關配置:
name: admin-system
# 前端配置
frontend:
component: "@serverless/tencent-website"
inputs:
code:
src: dist
root: frontend
envPath: src # 相對於 root 指定目錄,這里實際就是 frontend/src
hook: npm run build
env:
# 依賴后端部署成功后生成的 url
apiUrl: ${backend.url}
protocol: https
# TODO: CDN 配置,請修改!!!
hosts:
- host: sls-admin.yugasun.com # CDN 加速域名
https:
certId: abcdedg # 為加速域名在騰訊雲平台申請的免費證書 ID
http2: off
httpsType: 4
forceSwitch: -2
# 后端配置
backend:
component: "@serverless/tencent-egg"
inputs:
code: ./backend
functionName: admin-system
role: QCS_SCFFull
functionConf:
timeout: 120
vpcConfig:
vpcId: vpc-6n5x55kb
subnetId: subnet-4cvr91js
apigatewayConf:
protocols:
- https
2. 執行部署
執行部署命令:
$ serverless --debug
輸出如下成功結果:
frontend:
url: https://dtnu69vl-470dpfh-1251556596.cos-website.ap-guangzhou.myqcloud.com
env:
apiUrl: https://service-f1bhmhk4-1251556596.gz.apigw.tencentcs.com/release/
host:
- https://sls-admin.yugasun.com (CNAME: sls-admin.yugasun.com.cdn.dnsv1.com)
backend:
region: ap-guangzhou
functionName: admin-system
apiGatewayServiceId: service-f1bhmhk4
url: https://service-f1bhmhk4-1251556596.gz.apigw.tencentcs.com/release/
注釋:這里
frontend
中多輸出了host
,是我們的 CDN 加速域名,可以通過配置@serverless/tencent-website
組件的inputs.hosts
來實現。有關 CDN 相關配置說明可以閱讀 基於 Serverless Component 的全棧解決方案 - 續集。當然,如果你不想配置 CDN,直接刪除,然后訪問 COS 生成的靜態網站 url。
部署成功后,我們就可以訪問 https://sls-admin.yugasun.com
登錄體驗了。
源碼
本篇涉及到所有源碼都維護在開源項目 tencent-serverless-demo 中 admin-system
總結
本文基於騰訊雲的無服務器框架 Serverless Framework 實現,涉及到內容較多,推薦在閱讀時,邊看邊開發,跟着文章節奏一步一步實現。
如果遇到問題,可以參考本文源碼。如果你成功實現了,可以到官網進一步熟悉 Egg.js 框架,以便今后可以實現更加復雜的應用。雖然本文使用的是 Vue.js 前端框架,但是你也可以將 frontend
更換為任何你喜歡的前端框架項目,開發時只需要將接口請求前綴使用 @serverless/tencent-website
組件生成的 env.js
文件就行。
傳送門:
- GitHub: github.com/serverless
- 官網:serverless.com
歡迎訪問:Serverless 中文網,您可以在 最佳實踐 里體驗更多關於 Serverless 應用的開發!