V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
int64ago
V2EX  ›  分享创造

moky = (mock + proxy) // 一个简洁通用的前后端协作工具

  •  
  •   int64ago ·
    int64ago · 2016-10-29 08:43:21 +08:00 · 3187 次点击
    这是一个创建于 2952 天前的主题,其中的信息可能已经有所发展或是发生改变。

    --> GitHub 地址

    旧石器时代, Web 开发并不会去刻意区分前后端,写后端的人觉得写数据库跟写模板都是应该具备的技能。现在一般需要分前后端,因为大量前端框架和工具链的涌入(根源是需求复杂了),让前端可以跟后端独立开来。但是,无论是前端去写模板,亦或是完全前后端分离去写 JSX ,都脱离不了与后端进行数据交互。

    以上是本工具产生的动因,我们暂且将前后端交互的数据分为模板数据(由后端直接填充)和异步数据(通过 HTTP 接口),工具的作用就是平滑地进行数据交互过渡,降低沟通成本。

    名字由来

    在开发前期,后端可能并没有开始写或者没有写完,前端此时只能通过本地数据模拟实际数据进行布局和组件的调试,一般叫做 mock 数据。

    待前端写的差不多了,后端可能也差不多了,那么此时需要联调,因为联调的过程很可能伴随着大量的修复工作,前后端杂糅在一起部署的代价太高,高效的方式就是通过代理的方式直接从模拟数据切到后端数据,这里叫 proxy 。

    如果把 mock 和 proxy 结合起来,那么就叫 moky !

    使用说明

    项目的 GitHub 里面已经简单的说了下使用方法,不过我觉得还是有必要补充点额外的说明。

    首先,需要强调的是, moky 侧重点只有 mock 和 proxy ,因此可以做到代码也只有 200 行左右,市场上已经有很多人做这方面工作了,而基本都不能满足我的需求。

    使用跟 webpack 很类似,全局安装 npm i moky -g ,只需要一个配置文件,然后直接在配置文件 moky.config.js 所在目录运行 moky ,或者通过参数指定配置文件路径 moky -c /path/to/xxx.js

    但是,正确使用前一般需要先配置好 moky.config.js,下面针对配置文件做一个罗嗦的介绍:

    // 这里之所以需要 path ,是因为下面的文件路径都必须是绝对路径
    var path = require('path');
    
    module.exports = {
      // 本地监听端口,运行 moky 会起一个 server
      localPort: 3000,
      
      // 异步数据的 mock 目录路径
      asyncMockPath: path.join(__dirname, 'mock'),
      
      // 同步数据的 mock 目录路径
      viewsMockPath: path.join(__dirname, 'tplMock'),
      
      // 模板所在目录,如果你是完全前后端分离,没有模板,那至少有个 index.html 吧
      // 把这个 index.html 所在的目录当作模板目录即可
      viewsPath: path.join(__dirname, 'views'),
      
      // 这个并没有卵用,如果有 favicon 还是设置下吧
      faviconPath: path.join(__dirname, 'public', 'favicon.ico'),
      
      // 这里不要被 js 和 css 误导了,这里是设置静态资源的路由
      // 注意,其优先级比较高哦,所以不要漏了 /多了 /跟其它冲突了
      publicPaths: {
        '/css': path.join(__dirname, 'public', 'css'),
        '/js': path.join(__dirname, 'public', 'js'),
      },
      
      // 模板引擎的设置,具体参考 koa-views , moky 已经内置了几个模板引擎,可以直接设置就用
      // 注意两点:如果选择 freemarker 一定保证 JAVA_HOME 等设置是对的;
      // 如果是纯 HTML 页面,你随便选个模板引擎即可,推荐 nunjucks
      viewConfig: {
        extension: 'html',
        map: { html: 'nunjucks' },
      },
      
      // 这里为了解决很多 Web 容器采用的 Virtual Host 机制(一个 IP:PORT 通过域名对应多个服务)
      // 由于我们本地启动的可能是 http://localhost:3000 ,如果有 Virtual Host 机制则通不过的
      // 如果设置了 hostName ,在发送请求前程序会自动替换 Host 头为 hostName
      hostName: 'hacker-news.firebaseio.com',
      
      // 这里是 proxy 映射表,在启动的时候如果是 moky -e dev ,异步请求会自动走 dev 对应的 proxy
      // 如果没找到对应的,那么默认用本地的 mock 数据作为异步数据
      proxyMaps: {
        dev: 'https://hacker-news.firebaseio.com',
        local: 'http://localhost:8080',
      },
      
      // 这是页面路由的设置,这里的 key 是路由( URL 里见到的), value 是页面的相对路径
      // 路径相对于 viewsPath , 不用加后缀, viewConfig.extension 指明了
      urlMaps: {
        '/': 'index',
        '/page': 'page/index',
      },
    }
    

    最简单的试用就是全局安装 moky,然后 clone 项目,进入 example 目录,直接运行 moky

    先看下目录结构:

    ├── mock
    │   ├── get
    │   │   ├── test
    │   │   │   └── index.json
    │   │   └── v0
    │   │       └── item
    │   │           └── 2921983.json.json
    │   └── post
    │       └── index.json
    ├── moky.config.js
    ├── public
    │   ├── css
    │   │   └── main.css
    │   ├── favicon.ico
    │   └── js
    │       └── main.js
    ├── tplMock
    │   ├── index.json
    │   └── page
    │       └── index.json
    └── views
        ├── index.html
        └── page
            └── index.html
    

    直接运行 moky 会默认使用 mock 模式,数据流是这样的:

    • 我们浏览器打开 http://localhost:3000/page
    • 路由会根据我们的设置匹配一遍:静态资源 -> 页面 -> 异步接口,这里匹配到页面就停止了
    • 程序会去 tplMock/page/index.json 下拿模板数据,然后填充渲染返回
    • 此时页面里的静态资源的会被首先从 public 下路由
    • 然后会有个异步接口 GET v0/item/2921983.json,会最终被异步处理模块处理
    • 因为我们启动的时候是 mock 模式,于是会去 mock/get 文件夹找对应位置的 json 作为本地 mock 数据
    • 如果我们是 moky -e dev 启动的,那么 GET v0/item/2921983.json 会被从 proxyMaps.dev 反代

    遗留问题

    • 模板数据无法走 proxy 从远端获取
    • 对第三方登录 /认证不友好

    原文

    9 条回复    2016-11-03 17:22:12 +08:00
    SeanChense
        1
    SeanChense  
       2016-10-29 11:34:56 +08:00
    你一个人业余时间做的?
    int64ago
        2
    int64ago  
    OP
       2016-10-29 11:44:38 +08:00
    @SeanChense 是啊
    infun
        3
    infun  
       2016-10-30 21:49:29 +08:00 via iPhone
    大神就是厉害,比水河畔的厉害到不知哪里去了
    lllang
        4
    lllang  
       2016-10-31 19:35:49 +08:00
    特意过来支持下军哥,军哥就是叼。
    int64ago
        5
    int64ago  
    OP
       2016-10-31 20:59:46 +08:00
    @lllang 浪浪?
    lllang
        6
    lllang  
       2016-11-01 18:37:07 +08:00
    @int64ago 为毛你给我发的消息都没有提醒。我来强行你支持一波。想过段时间不忙了把我们这边的 mock 加一个热加载
    int64ago
        7
    int64ago  
    OP
       2016-11-01 18:56:23 +08:00 via Android
    @lllang @Livid
    已经有多个人反应我的回复他们收不到提醒
    wangcansun
        8
    wangcansun  
       2016-11-03 16:50:22 +08:00   ❤️ 1
    楼主很有思想啊。。。有这么几个问题啊

    1. 有没有考虑过 rest 的问题,资源很多,岂不是有很多 json ,管理起来会不会不方便
    2. 在我看来 mock 数据是一项主要功能,但是 API 文档也是一个更重要的功能,楼主有没有想过

    国内有阿里系的 RAP 来实现 mock + 文档
    国外有 swaggerh 和 apiblueprint ( apiary.io 我更喜欢的在线文档 + mock + api 测试)

    自己也根据 apiblueprint 的第三方插件试过一个,觉得挺不错的
    https://github.com/wangcansunking/api-blueprint-mock
    有时间可以试试

    欢迎交流
    int64ago
        9
    int64ago  
    OP
       2016-11-03 17:22:12 +08:00
    @wangcansun 恩,你说的挺对的

    因为我公司已经有比较优秀的 mock 和 接口管理工具: https://nei.netease.com/

    (虽然这个也有离线 mock 调试的功能,但是我认为不好用,所以一般只用于跟后端协作接口,以及 mock 数据生成)

    所以我就把工具的功能限定在 mock + proxy ,其它如果加进去的就太冗杂了,而且我也不觉得做的比别人的好
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3255 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 12:16 · PVG 20:16 · LAX 04:16 · JFK 07:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.