Reid

vuePress-theme-reco Reid    2018 - 2024
Reid Reid

Choose mode

  • dark
  • auto
  • light
TimeLine
分类
  • 后端
  • AI
  • 英文翻译
  • 运维
标签
我的GitHub (opens new window)
author-avatar

Reid

16

文章

25

标签

TimeLine
分类
  • 后端
  • AI
  • 英文翻译
  • 运维
标签
我的GitHub (opens new window)
  • 前后端共享代码

    • 需求
      • 解决方案
        • P1 创建公用库
        • P2 拉取子模块的代码
        • P3 部署到 Jenkins
      • ts 声明文件
        • 总结

        前后端共享代码

        vuePress-theme-reco Reid    2018 - 2024

        前后端共享代码


        Reid 2022-07-30 Git Node.js TypeScript

        # 需求

        公司的客户端分为小程序端和后台管理端,对应的代码仓库有 4 个:

        • 小程序
        • 管理后台
        • 小程序接口
        • 管理后台接口

        而一个项目里的常量枚举和工具,各个仓库都会用到的,而大部分都是通用的,直接的复制粘贴肯定会出现某一仓库没有跟最新的代码统一的问题。

        # 解决方案

        因为公司用的 GitLab 来托管代码,所以可以用 git 的 submodule 功能,创建一个仓库作为子模块,这样所有代码仓库都可以引用该子模块。

        # P1 创建公用库

        创建一个仓库作为公用库:

        • constant 放常量枚举
        • util 工具类
        • management-api 管理后台接口请求、响应的数据结构
        • wechat-api 小程序接口请求、响应的数据结构

        # P2 拉取子模块的代码

        在各个仓库代码中执行:

        git submodule add http://${子模块仓库地址}.git src/module/cm-common
        

        这样在项目根目录下就会出现一个.gitmodules的文件,里面会记录子模块的信息:

        有了这个.gitmodules文件后,其他小伙伴要同步代码只需要执行一下该命令:

        git submodule update --init --remote --recursive
        

        这样就会拉取最新的子模块代码了。

        # P3 部署到 Jenkins

        注意,执行了上面命令后,如果子模块的代码有更新,本地子模块里的commit_id会发生变更,这个要一并提交上去,我们后续在 Jenkins 部署的时候有用。

        然后我们在 Jenkins 任务里的源码管理里新增一个Additional Behaviours,选择高级的子模块行为。

        接着勾选下面的几个选项,这样 build 的时候 Jenkins 就会去拉取submodule里面的代码了。

        # ts 声明文件

        除了常量枚举和工具可以放到公共库,我们还可以把接口的请求和响应的数据结构也写在公用库里,这样前端传参和拿数据都不会出现传错和拿错:

        后端同学编写的声明文件:

        // management-api/user.ts
        import { Basic } from "./basic";
        
        export interface GetSimpleListResult extends Basic {
          data: {
            rows: {
              id: number;
              username: string;
              phone: string;
            }[];
          };
        }
        
        export interface GetSimpleListParams {
          page: number;
          pageSize: number;
          name?: string;
          mobile?: string;
        }
        

        前端同学引入和使用:

        import {
          GetSimpleListParams,
          GetSimpleListResult,
        } from "@/module/cm-common/management-api/user";
        
        export async function getUserList(
          params: GetSimpleListParams
        ): Promise<GetSimpleListResult> {
          return request("/api/v1/user/simple-list", {
            method: "GET",
            headers: {
              "Content-Type": "application/x-www-form-urlencoded",
              Authorization: `${token.get()}`,
            },
            params: {
              ...params,
            },
            ...(options || {}),
          });
        }
        

        # 总结

        目前这套方案还是挺舒服的,不过小程序接口和管理后台接口仓库还是会有很多service相关的代码重复,这一块就不太适合放到子模块里去了,应该用微服务比较好,以后再想了~