Monday Apps 开发初体验(二)- 创建 App

447 阅读6分钟

背景

上一篇文章《Monday Apps 开发初体验(一)- 基本概念了解》初步了解了一下 Monday 的基本概念,有了这些概念基础,再去开发 App 就比较顺畅了,我们主要参考 Quickstart guide,开搞!

App 基本信息

进入到 developer 页面,新建一个 App 后我们发现除了 App 名称、介绍等,还有以下比较关键的信息。这些可以作为「平台 - 插件」模式的设计参考。

App Credentials

App 有一些凭证信息,包括 OAuth 用的 Client ID、Client Secret,用于校验接收到的消息是否合法的 Signing Secret,和 App ID。

image.png

从上图中我们还能看到有 Webhooks 的能力。我们点进去看一下

Webhooks

image.png

从上图中我们可以了解到,Monday App 的生命周期有:安装、卸载、App 订阅的各种状态,包括:创建、变更、取消、更新、开始、结束等。

webhook 携带的信息除了信号种类 type,还有就是 App 和用户的基本信息 data 了。

也就是说当 App 运行到上面的任何生命周期的时候,都会触发我们提供的 URL 接口,并且携带以上信息给我们。然后我们就可以做一些我们想做的事情了。比如自己统计 App 安装和卸载的数量等。

初始化项目

本地生成项目

根据教程,我们选择 Features -> Board Views -> Quickstart - ReactJS 来初始化项目。最后一步你会看到下图,会等待你执行命令,然后把生成的 URL 粘贴到输入框里。

image.png

按照说明,在自己电脑的命令行里运行下面的命令,就能够完成项目的初始化。

npx @mondaydotcomorg/monday-cli@latest scaffold run ./ quickstart-react -t board-view-10087609

注意,命令执行完后,不会自动退出,而是直接启动了本地开发的命令,这时候直接访问 http://localhost:8301 来查看初始化的效果。

但这不是关键,关键是要往上翻一下命令行的记录,找到类似下面这条记录,把里面的 URL 粘贴到输入框。

[16:18:57.738] INFO: your url is: https://board-view-10087609.tunnel.monday.app

我们打开这个 URL,可以发现展示的内容与 http://localhost:8301 内容是一样的。我修改本地代码,localhost 的页面可以实时响应,也就是热更新。这很正常,但是!!!神奇的是我刷新了一下上面的 URL,内容竟然也跟着更新了,而且这个 URL 是可以被其他人访问的。这就有点黑科技了!回头可以研究一下。

项目分析

quickstart-react 目录结构如下:

.
├── node_modules
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
├── src
│   ├── App.css
│   ├── App.js
│   ├── index.css
│   ├── index.js
│   └── serviceWorker.js
├── README.md
├── package-lock.json
└── package.json

再看一下 package.json 的主要内容:

  "scripts": {
    "start": "npm run stop && concurrently \"npm run server\" \"npm run expose\"",
    "build": "react-scripts build",
    "expose": "mtunnel -p 8301",
    "server": "react-scripts start",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "stop": "kill-port 8301 && kill-port 4049 && kill-port 4040"
  },
  "dependencies": {
    "monday-sdk-js": "^0.1.4",
    "monday-ui-react-core": "^1.54.0"
  },
  "devDependencies": {
    "@mondaydotcomorg/tunnel": "^0.4.1",
    "concurrently": "^5.2.0",
    "cross-port-killer": "^1.2.1",
    "eslint-config-react-app": "^7.0.1",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-scripts": "^5.0.1",
    "sass": "^1.54.8"
  }

从目录结构和 package.json 的内容,我们不难发现这是以 create-react-app 为基础搭建的 PWA 项目,甚至很多 rect-scripts 的命令和 serviceWorker.js 原封不动的保留了。

我们再来看一下它的依赖,reactsaas 等都装到了 devDependencies 里,我们可以推测这些包都已经被 Monday 内置提供了,这很好理解,除了能节省体积,在加载、编译等效率上面也是有明显好处的。

稍微研究了下,发现 scripts 里的 mtunnel 命令,是由 @mondaydotcomorg/tunnel 提供的。就是这个命令让本地的内容可以同步到「外网」。介绍的原文如下:

Monday.com Tunnel exposes your localhost to the world for easy testing and sharing! No need to mess with DNS or deploy just to have others test out your changes. Great for testing your app feature directly on monday.com.

详见:www.npmjs.com/package/@mo…

再来看 dependencies 的内容,只有 monday-sdk-jsmonday-ui-react-core,很明显,一个是 JSSDK,一个是 UI 组件库。这两块需要单独研究和分析,我们先按下不表。

上传发布

主要分以下几步:

  1. 本地运行 npm run build,生成 build 目录;
  2. 将 build 目录压缩成 build.zip 文件;
  3. 在 App 的 Feature Details 页面找到 Feature Build,点击 New Build,上传 zip 文件;

完成后就算发布成功了。这时候如果你的用户账号和 developer 账号是一个的话,你的用户侧就会收到一个消息提示,告诉你已经上传成功。

然后我们任意打开一个 Board 页面,点击 Add View 按钮 -> 选择 Apps -> 把 App 列表往下拉,在 Development Apps 里找到我们刚发布的 feature -> 点击 Open in board。就能在页面里看到我们刚开发的页面了。

image.png

可以看到,这里的 user_id 加载出来了,是真实数据(在本地开发时显示的始终是 still loading)。获取方式是通过 JSSDK,具体可以看 App.js 里面的代码。

加载方式推测

如下图,打开开发者工具,我们可以发现整个 Board View 是加载在一个 iframe 里的。这个 src 是可以在浏览器里面单独打开的,但是 user_id 是获取不到的。

image.png

我们还可以看到,这个 src 后面跟了一个很长的 token,看格式猜测是 base64,直接上 C 老师解码后给的分析吧:

image.png

再来看下笔者主动 console 的内容,来看下 debug 情况。

image.png

image.png

点进去看,完全是源码。证明我们打包生成的 map 文件是生效的。想想也是,毕竟是运行在 iframe 下面的,加载 js、css 什么的,也不用做太多处理。

不过这里就涉及到源码泄露问题了。后来笔者尝试了下在压缩 zip 之前把 map 文件删掉,结果就变成了下图这样:

image.png

明显是混淆过后的结果了。至于是否上传 map 文件,就看你是否介意源码泄露了。

总结

开发一个 Board View 的 Monday App Feature 其实不难,几乎跟开发一个普通的 React App 没什么区别,这极大地降低了开发门槛。

发布方式也很简单,就是把打包产物上传即可,应该是可以自动化实现的。有一点可能会比较有争议,就是 Monday 没有版本的概念。这边 upload 了 zip 之后,用户那边自动就升级成最新版了。这种做法有利有弊,有时间的话去深挖一下 Monday 这样设计的逻辑是什么。

这里笔者会存在一个疑问,Board View 是用 iframe 方式实现隔离的,这无疑是隔离非常彻底的一种方案。至于 iframe 引起的数据通信之类的问题,应该就是 JSSDK 封装的方法去实现的。

笔者的疑问就是,难道 Monday 所有的 App Feature 都是用 iframe 实现的吗?会有更「小」的组件之类的 Feature 无法用 iframe 实现吗?咱们后续接着研究……