背景
前面两篇文章:
已经完成了一个简单的 Board View Feature 的开发和上传发布。接下来我们该来分析一下 Monday 在使用频率最高的(前端看来)开发者工具:JSSDK 和 UI 组件库,是怎么设计的。
JSSDK
Monday 提供的 SDK 都放在 github 上开源了,相关文档如下:
SDK 这里我们主要关注 2 块,一个是鉴权,一个是 API 设计思路。
鉴权
先来看鉴权,下面是 Monday 文档里对鉴权的解释:
When used for client-side development, SDK methods that require acting on behalf of the connected user will work out-of-the-box by communicating with the parent monday.com running application. You’re not required to initialize the SDK client with any explicit credentials.
Methods that use seamless authentication (including
monday.api
andmonday.storage
) offer capabilities that are scoped based on the permissions of the logged-in user and the scopes you have configured in your app.
通常在使用这种 SDK 的时候,都会有个 init 方法,让你传入 id、secret 什么的内容,来进行鉴权。但是上文的描述,再结合之前 guides 里面的 Demo,Monday 的 SDK 在使用的时候,的确没有鉴权的步骤。笔者对这点还挺好奇的,我们去看一下它的源码吧。
在其 api
方法里,笔者发现了一些端倪,里面有这样的逻辑:
api(query, options = {}) {
const params = { query, variables: options.variables };
const token = options.token || this._apiToken;
const apiVersion = options.apiVersion || this._apiVersion;
if (token) {
return mondayApiClient.execute(params, token, { apiVersion });
} else {
return new Promise((resolve, reject) => {
this._localApi("api", { params })
.then(result => {
resolve(result.data);
})
.catch(err => reject(err));
});
}
}
有 token
的时候,走 mondayApiClient
,没 token 的时候走 this._localApi
。mondayApiClient
是 Nodejs 服务端的时候走的(JSSDK 是浏览器端和 Nodejs 服务端公用的,入口有判断),所以我们主要看后者。在 _localApi
的代码里有了明显的发现,它使用 window.parent.postMessage
把消息发给了父窗口。
我们在前面的文章提到过,App 的页面是放在 iframe 里执行的,所以用 postMessage
向父窗口发消息,由父窗口返回数据,貌似是个很好的方式,不需要在 App 内进行鉴权了。
好的,答案已经呼之欲出了。Monday App 把所有的行为都发送给了父窗口,也就是 Monday 平台端,所有需要鉴权(和不需要鉴权)的操作都是在平台端发起的,自带鉴权。原来 Seamless-authentication 是这么实现的。果然巧妙!
不过这里笔者还有一丝疑虑,如果我能想办法给 Monday 的应用里面「黑进去一个 iframe」,是不是理论上我就可以获取到当前用户的所有信息了呢?这个地方的安全性笔者还需要思考一下,前面的文章有说过,这个 iframe 的 URL 里面有 JWT 的 token,也许跟这里有关。嗯~~挺有意思~~
API 设计
截取文档内容如下:
SDK Object | Capability |
---|---|
monday.api |
Performing queries against the monday.com API on behalf of the connected user |
monday.listen |
Listen to client-side events on the monday.com client running this app |
monday.get |
Retrieve information from the monday.com client running this app |
monday.execute |
Call an action on the monday.com client running this app |
monday.storage |
Read/write to the Storage API, a key-value storage service for apps |
monday.set |
Setup data inside an app |
我们挨个看一下,
api
是用于发起请求的,listen
是用来监听事件的,get
是用来获取当前静态(相对)数据的,这几个不需要太多展开,使用的时候查文档就好;execute
能够打开/关闭 Modal 弹窗、弹出提示消息这些功能;storage
看起来就是给 App 提供的类似 localStorage 的存储;set
只能设置settings
和location
的数据,详见文档;
大概看了一下它的源码,几乎都是用 this._localApi
向平台端发送的消息,由平台端去处理的。嗯~这种设计也挺巧妙的,这让 SDK 的代码好简单啊~
UI 组件库
同样,Monday 的 UI 组件库也开源了,叫 Vibe Design,相关文档如下:
首先看一下依赖:
"dependencies": {
"@popperjs/core": "2.11.6",
"a11y-dialog": "^7.5.2",
"autosize": "^5.0.1",
"body-scroll-lock": "^4.0.0-beta.0",
"classnames": "^2.3.2",
"lodash-es": "^4.17.21",
"monday-ui-style": "0.1.160",
"prop-types": "^15.8.1",
"react-dates": "21.8.0",
"react-inlinesvg": "^3.0.1",
"react-popper": "^2.3.0",
"react-select": "^3.2.0",
"react-transition-group": "^4.4.5",
"react-virtualized-auto-sizer": "^1.0.7",
"react-window": "^1.8.7",
"react-windowed-select": "^2.0.4",
"style-inject": "^0.3.0"
},
从依赖我们基本可以判断,它不是依赖了某些成熟组件库进行的摩改,直接就是造了套轮子。粗略翻看了一下 Vibe Design 的主页,毫无疑问是用 storybook 搭建的(浏览器 Tab 上的 Icon 都没换)。内容也很完整,设计哲学、色彩规则、交互原则等都很靠谱,感觉质量很不错,全篇看下来应该会很有收获。
笔者最喜欢的是它的 Do's and don'ts
模块的内容,非常直观的演示了应该怎样做,不应该怎样做,可谓对于读者来说非常友好了。
另外值得一提的是它的 Hooks,可以说非常全面了。笔者还没有细看,但是光看名字就已经能够体会到设计者面面俱到的这种思路了。厉害!!(也可能是笔者孤陋寡闻,大惊小怪了)
总结
Monday 的 JSSDK 设计,有一个严苛的前提:App 功能的底层实现是使用的 iframe。这样才能做到 Seamless Auth,顺带着让 SDK 的逻辑非常简单(只需要往平台端 postMessage 就行了)。嗯~ 还是很巧妙的。
组件库只是简单扫了一下,初步判断质量还是很高的,从设计哲学到组件使用最佳实践,整个组件库的设计很有高度,大概率细节也不会差(官网有开发团队的照片,嗯~研发妹子质量不错~)。
写到这里,Monday 的初步探索已经差不多了,接下来笔者打算看一下比较老牌的 JIRA。看是否能碰撞出不一样的火花~