前言
之前看過國外一個開發者tipsy用kotlin開發了一個github profile summary,我覺得他的想法非常棒,所以我想著用Node的技術棧來實現一遍。
我的技術棧是Vue和Koa,所以在實現上我就用了它們分別來做前端和後臺。
先放張效果圖:

專案結構
.
├── LICENSE
├── README.md
├── app.js
├── build
│ ├── build.js
│ ├── check-versions.js
│ ├── logo.png
│ ├── utils.js
│ ├── vue-loader.conf.js
│ ├── webpack.base.conf.js
│ ├── webpack.dev.conf.js
│ └── webpack.prod.conf.js
├── config
│ ├── dev.env.js
│ ├── index.js
│ └── prod.env.js
├── index.html
├── jsconfig.json
├── now.json
├── package.json
├── server
│ ├── controllers
│ ├── middlewares
│ ├── router
│ └── utils
├── src
│ ├── App.vue
│ ├── assets
│ ├── components
│ ├── main.js
│ ├── router
│ └── views
├── static
└── yarn.lock
複製程式碼
基本就是vue-cli生成的專案結構+Koa後端的專案結構,這個就不再贅述。
思路
利用github的api來獲取所需要的使用者資訊,然後通過獲取的使用者資訊來構建使用者的github簡歷。一開始我打算用的也是github的RESTful api。不過馬上我就遇到問題:
- github的RESTful api是有分頁限制的。也就是比如我無法一次性獲取一個使用者的點過star的倉庫,而需要判斷是否有下一頁、是否要請求到最後。
- RESTful的api會返回一堆我不需要的資料。而且資料量一大對效能要求會比較高。比如我只想要一個使用者的倉庫總數,我卻需要獲取完他所有的倉庫我才能知道總數。
- 要發多個RESTful請求才能勉強完成一些功能,代價是耗時巨大。
綜上,無法再繼續用RESTful api來實現我想要的效果。於是我把目光轉移到了GraphQL api上了。相信很多關注前端的朋友們對於這個詞並不陌生,但是真正用上的少之又少——畢竟目前還是RESTful api為主的開發模式。
我也一樣,一開始看GraphQL api的那些定義、結構什麼的,感到非常困難。不過藉助Github的GraphQL exploer以及Github GraphQL的官方開發者論壇,總算是大致實現了我想要的功能。
github提供的GraphQL api有一些特別有用的屬性比如totalCount
,就能計算一些引數的總數,比如上面說到的一個人擁有的倉庫總數,而不用一個個倉庫都獲取才知道總數。
目前來說,GraphQL還不像RESTful那樣通過直觀的url來查詢資料,而是通過使用者自定義的graphql語句來實現需要的資訊的查詢。 比如統計使用者Molunerfinn的倉庫總數:
{
user(login: "Molunerfinn"){
repositories(affiliations: [OWNER COLLABORATOR] isFork: false){
totalCount
}
}
}
複製程式碼
返回結果:(跟你的graphql結構是一致的)
{
"data": {
"user": {
"repositories": {
"totalCount": 24
}
}
}
}
複製程式碼
所以現在node社群還沒有什麼特別好的庫來像資料庫的ORM一樣幫我們簡化寫graphql的步驟。所有的請求都必須自己手寫graphql。
專案流程
由於github的api查詢數量限制,在有token的情況下一小時是5000次,所以tipsy的github profile summary做了限制,查詢某個使用者的github profile summary時必須先star這個倉庫,才可以查詢。因此我也做了一個這個的限制。
所以我在後端Koa處做了檢測的介面,用於檢測使用者是否star,既可以防止惡意刷請求又可以給自己漲一波star豈不美哉~
前端Vue頁面這邊發起請求後判斷返回值,如果是false說明並沒有star,所以就不讓其跳轉的具體的profile頁面。
async checkStar () {
this.loading = true
let res = await this.$http.get(`/api/check-status/${this.username}`)
if (res.data.success) {
this.$router.push({
name: 'Profile',
params: {
username: this.username
}
})
localStorage.setItem('github-profile-token', res.data.token)
} else {
this.invalid = true
this.invalidUsername = this.username
this.loading = false
}
}
複製程式碼
如果請求結果正確,會把後端返回的json web token存入localStorage裡用於鑑權。
當然,如果使用者直接跳轉profile頁面,也會在路由的鉤子裡判斷token存不存在?如果存在,放行。如果不存在,請求一遍使用者是否star,如果star,放行,否則不放行。
其實業務邏輯都很簡單,相信做過node前後端的你們能很快理解。為了減輕伺服器的負擔,後端在通過GraphQL請求完資料後,直接返回前端,利用前端瀏覽器的算力,來把資料組織出來通過chart.js來渲染出好看的圖表:

當然為了方便大家分享和收藏,我也做了分享和儲存為圖片的功能:

為了能在手機端順暢瀏覽,我也做了移動端的響應式適配~
部署
我採用的是now這個平臺來部署,它能夠部署node的應用,所以我就很開心的把我的應用部署上去啦~它會自動把我Koa暴露出去的埠反代到80埠,所以你可以直接訪問https://gh-profile-summary.now.sh這個地址而不用自己來操心埠問題啦!
由於now.sh的免費額度每月只有1G,所以我還是切換到了我自己的伺服器上了~
具體的開發經驗和踩的坑之後我會發一篇文章來細說~可以關注我的掘金個人主頁~
歡迎大家體驗:
也可以分享你的github總結給你的朋友們啦~
寫文章可以得非同步社群的書!愛讀書的技術人都在非同步社群。我想要讀《React Native移動開發實戰》,希望你也能夠喜歡。參與寫作換書活動。