在 API 和前端之间共享接口

Posted

技术标签:

【中文标题】在 API 和前端之间共享接口【英文标题】:Share interfaces between API and frontend 【发布时间】:2019-07-23 06:59:46 【问题描述】:

我正在开发双方。 API 在 nest.js 中,前端在 Angular 中。双方都使用打字稿,我面临共享接口的问题,应该是一样的。例如 ILoginRequest 和 ILoginResponse。我想将这两个项目放在不同的 GIT 存储库中。我应该将 GIT 子模块与第三个共享 GIT 存储库一起使用,还是以某种方式创建共享 npm 包,或者是否有一些好的工具可以自动(从 swagger 定义)生成类到前端或其他任何东西?

编辑:要从 swagger 为客户生成代码,请查看 openapi-generator

【问题讨论】:

创建一个 npm 包将是最简单的方法。你只需要你的接口和一个 package.json 来发布它。 【参考方案1】:

面临同样的问题并研究了一些替代方案。以下是我的考虑和选择:

    将实体定义分离到单独的代码库中 - 可能在不同的 git 存储库中。这里的问题是 Nest 使用了 Angular 不理解的装饰器。这意味着我必须将 Nest 作为依赖项包含在内,这似乎是个坏主意,或者创建存根装饰器——浪费时间。拒绝 创建节点包 - 与 #1 相同的问题。拒绝 复制粘贴。后端和前端项目都有一个实体文件夹。后端的实体是用 TypeORM 装饰器(对我来说)装饰的 classes。我将它们复制到前端的实体目录并将它们转换为 interfaces,因为您从 httpclient 库(应该符合接口的对象 - 不是类实例)中得到返回。采用

最后,看看 cmets,我看不出 GraphQL 在这方面有何帮助,因为您没有尝试利用现有界面 - 想听听某人的意见 :)

【讨论】:

关于 graphql:您可以使用正在运行的服务器中的脚本创建(和更新)前端类型定义。这是一种在存储库之间(半)自动共享类型定义的简单方法,同时仍然具有完全控制权并失去耦合。看看 apollo schema:download & apollo client:codegen 我不确定选项 3 是如何工作的,当它是两个不同的存储库时? 如何使用monorepo(例如Yarn workspaces,lerna)进行分享【参考方案2】:

注意:我最近偶然发现了typeorm-entitysharer,它“可用于基于相同的 TypeORM 实体创建客户端/服务器类,允许您共享它们。”它使您可以更好地控制要共享的内容,您可以查看他们的示例。我没有选择使用它,因为我猜这对我来说有点矫枉过正。但是,这就是我构建上一个项目的方式:


我将前端和后端放在一个存储库中,但是我想您可以将它们分开,但是您仍然需要以某种方式将它们彼此相邻。文件结构将是这样的:
workspace
  ├─backend        <- repo #1
  │   ├─src
  │   │   ├─shared <- shared code goes here
  │   │   └─proxy.ts
  │   └─tsconfig.json
  └─frontend       <- repo #2
      ├─src
      │   └─proxy.ts
      └─tsconfig.json

那么在backend/tsconfig.json你介绍


    ...
    "paths": 
        "@shared/*": [ "src/shared/*" ],
    

frontend/tsconfig.json你介绍


    ...
    "paths": 
        "@shared/*": [ "../backend/src/shared/*" ],

        // if you're using TypeORM, this package has dummy decorators
        "typeorm": [ "node_modules/typeorm/typeorm-model-shim.js" ]
        // you can do the same for other packages, point them to dummy paths

        // altirnatively you can route the shared imports through the proxy.ts
        // and replace them in frontend/src/proxy.ts with dummy ones
    

别忘了在你的前端npm i typeorm

示例

假设我在backend/src/shared/user.entity.ts 有这个

import  PrimaryGeneratedColumn, Column  from 'typeorm';

export class UserEntity

    @PrimaryGeneratedColumn() id: number;
    @Column() name: string;
    @Column() password: string;

现在,我可以像这样在任何地方使用它:

import  UserEntity  from '@shared/model/user.entity';

在后端,很明显,在前端,@shared/model/user.entity 被映射到 ../backend/src/shared/model/user.entity,而实体内部的 import from 'typeorm' 被映射到虚拟包。

【讨论】:

谢谢,对我来说,这是无需维护实体仓库的方式 嘿,Peter Dub,你能把这个标记为答案吗? 在我看来,这里几乎是一个 monorepo,请查看 nx.dev 以获得用于管理 mongo repos 的非常棒的工具集【参考方案3】:

在浪费了一整天的时间试图让它工作后,我遇到了NX/NRWL。

它基本上只是一个 CLI,其中包含有助于正确构建应用程序的工具。我能够在大约一个小时内使其正常工作。单一存储库中的共享接口是可行的方法。

【讨论】:

以上是关于在 API 和前端之间共享接口的主要内容,如果未能解决你的问题,请参考以下文章

Eolink是国产API接口管理的无冕之王

Eolink是国产API接口管理的无冕之王

Eolink是国产API接口管理的无冕之王

前端 API 接口数据模拟 (Mock)

在 Typescript 项目之间共享接口

java后台接口怎么方便返回restful数据