V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
scf10cent
V2EX  ›  Serverless

Serverless + Egg.js 后台管理系统实战(下)

  •  
  •   scf10cent · 2020-02-28 09:49:48 +08:00 · 6140 次点击
    这是一个创建于 1513 天前的主题,其中的信息可能已经有所发展或是发生改变。

    ▎阅读本文前请先食用《 Serverless + Egg.js 后台管理系统实战(上)》,在上集中,我们介绍了 Egg 和 Serverless 的基础知识、准备和后端服务开发。本篇将承接上文,继续介绍后端服务部署以及前端开发和部署的部分。文末附带了所有源码,供想体验的朋友参考~

    Let's begin !

    后端服务部署

    到这里,后端服务的登录和注销逻辑基本完成了。那么如何部署到云函数呢?可以直接使用 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 的前端模板。

    我们需要做如下几部分修改:

    1. 删除接口模拟:更换为真实的后端服务接口
    2. 修改接口函数:包括用户相关的 frontend/src/api/user.js 和文章相关接口 frontend/src/api/post.js
    3. 修改接口工具函数:主要是修改 frontend/src/utils/request.js 文件,包括 axios请求的 baseURL 和请求的 header。
    4. 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/routerfrontend/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-demoadmin-system

    总结

    本文基于腾讯云的无服务器框架 Serverless Framework 实现,涉及到内容较多,推荐在阅读时,边看边开发,跟着文章节奏一步一步实现。

    如果遇到问题,可以参考本文源码。如果你成功实现了,可以到官网进一步熟悉 Egg.js 框架,以便今后可以实现更加复杂的应用。虽然本文使用的是 Vue.js 前端框架,但是你也可以将 frontend 更换为任何你喜欢的前端框架项目,开发时只需要将接口请求前缀使用 @serverless/tencent-website 组件生成的 env.js 文件就行。


    传送门:

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2602 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 05:04 · PVG 13:04 · LAX 22:04 · JFK 01:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.