用 NodeJS 開發(fā)一版在線流程圖網(wǎng)站
源碼:https://github.com/maqi1520/Clone-processon
背景
對于程序員來說,每天除了寫代碼,接觸較多的可能是各種圖表了,諸如流程圖、原型圖、拓?fù)鋱D、UML 圖以及思維導(dǎo)圖等等,我們較為熟悉的是 ProcessOn 了,可能你還在用 ProcessOn 免費(fèi)版, 總共十張圖,畫完這張圖下載下來刪除再重新畫另一張。前些天,在群里看到有小伙伴在邀請新用戶注冊,可以獲得 3 個(gè)文件數(shù)。奈何大家都注冊了,沒注冊的只有少數(shù),作為前端程序員,我在想是否可以將它的 js 扒下來,在本地起一個(gè)服務(wù)器使用?
獲取前端靜態(tài)資源
說干就干,使用 chrome 右鍵另存為 ,可以直接將這個(gè)網(wǎng)站使用到的靜態(tài)文件保存下來,但是保存下來的靜態(tài)資源目錄都自動(dòng)替換了本地,但我想要的是跟線上一樣的目錄結(jié)構(gòu)。
難道右鍵一個(gè)一個(gè) JS 另存為嗎?
并不是,可以使用一個(gè)chrome插件?Save All Resources?[1]?把整個(gè)網(wǎng)站的靜態(tài)資源 down 下來,
安裝之后在chrome devTools 會(huì)多出一欄

點(diǎn)擊?save All Resources??就可以了,全部down下來了.
解壓之后,我們一起來看看目錄

不光這個(gè)域名下的靜態(tài)資源,其他域下的靜態(tài)資源也都 down 下來了,其實(shí)這已經(jīng)完成一半了。
將全部資源拷貝出來,然后將 html 文件重命名為?index.html?使用?http-server[2]?在當(dāng)前目錄起一個(gè)服務(wù),這樣就成功訪問了。能夠畫流程圖了,只不過數(shù)據(jù)不能保存。
那么該如何保存數(shù)據(jù)呢?
開發(fā)一個(gè) chrome 插件
一開始我的想法是開發(fā)一個(gè) chrome 插件,類似掘金的chrome插件[3]一樣, 點(diǎn)擊就可以打開,然后重寫 jquery 的$.ajax?的方法,使用?localStroage?存儲(chǔ)數(shù)據(jù),這樣可以更加方便我們使用,實(shí)現(xiàn)起來應(yīng)該不難吧。
然后就去找如何開發(fā)一個(gè) chrome extension。我在 github 找到了?chrome-extensions-samples[4]?然后對著里面的 demo,嘗試了下。但結(jié)果遂不人愿,因?yàn)?ProcessOn 中大量使用了eval方法。chrome-extensions 認(rèn)為這個(gè)方法不安全。
又然后根據(jù)官網(wǎng)?Using eval in Chrome extensions[5],根據(jù)里面的介紹,將 html 放入一個(gè)?iframe?中, ?這樣可以就可以了。略微開心了一下,一起看下我們的 hello Word Chrome extensions。

接下來準(zhǔn)備保存數(shù)據(jù)。
iframe 內(nèi)部想要跟父容器的通信可以使用 parent,又遇到了問題。

因?yàn)?chrome extension iframe 是直接打開的,并不是在一個(gè) http 服務(wù)下,然后我又試了?postMessage?等方法,還是不能通信。
既然不能做到純離線的,那只能就開發(fā)一個(gè)在線版本好了??
Nodejs 開發(fā)
技術(shù)棧
后端:?express.js[6] 數(shù)據(jù)庫:?postgres[7] ORM:?prisma[8] Authentication:?github OAuth[9] 前端:?Jquery[10]
這邊的技術(shù)棧我就直接選用了我博客[11]的相同的技術(shù)棧,畢竟注冊登錄這些代碼都能直接拿過來用。
感興趣的同學(xué)可以看下我之前的文章?用 NextJS 和 TailwindCSS 重構(gòu)我的博客[12]
表結(jié)構(gòu)
接下來就是根據(jù)接口,進(jìn)行建表


根據(jù)首次加載查看詳情的 get 請求 可以看到請求數(shù)據(jù),他是將 Json 作為字符串返回的,我估計(jì)他使用的是 MongoDB 數(shù)據(jù)庫,id 跟 MongoDB id 長度一致。
datasource?db?{
??provider?=?"postgresql"
??url??????=?env("DATABASE_URL")
}
generator?client?{
??provider?=?"prisma-client-js"
}
model?User?{
??id?????????????String????@id?@default(uuid())
??name???????????String?
??password???????String
??email??????????String????@unique
??avatar_url?????String?
??emailCheckCode?String??//郵箱驗(yàn)證唯一code
??checked????????Boolean???@default(true)?//郵箱是否驗(yàn)證
??posts??????????Post[]
??historys???????History[]
??charts?????????Chart[]
}
model?Comment?{
??id??????String??@id?@default(uuid())
??shapeId?String?
??name????String?
??replyId?String?
??time????Int
??content?String
??userId??String
??chartId?String
??chart???Chart???@relation(fields:?[chartId],?references:?[id])
}
model?Chart?{
??id?????????String????@id?@default(uuid())
??title??????String
??deleted????Boolean???@default(false)
??elements???Json
??page???????Json
??theme??????Json?
??ownerId????String
??owner??????User??????@relation(fields:?[ownerId],?references:?[id])
??historys???History[]
??comments???Comment[]
??createTime?DateTime??@default(now())[email protected]
??lastModify?DateTime??@default(now())[email protected]
}
model?History?{
??id?????????String???@id?@default(uuid())
??title??????String
??remark?????String
??elements???Json
??page???????Json
??theme??????Json?
??userId?????String
??user???????User?????@relation(fields:?[userId],?references:?[id])
??chartId????String
??chart??????Chart????@relation(fields:?[chartId],?references:?[id])
??createTime?DateTime?@default(now())[email protected]
}
然后是歷史表,一對多,一張圖對多張歷史,每次操作都更新當(dāng)前數(shù)據(jù)后,然后插入歷史表。
總體來說,實(shí)現(xiàn)起來不是很難。
部署
想要部署的同學(xué) 可以移步?github[13],里面有寫部署步驟。
TODO
當(dāng)然還有一些比較困難的還未實(shí)現(xiàn), 比如:
websocket 多人同步編輯 文件上傳 生成縮略圖 分享頁面
總結(jié)
ProcessOn 沒有做代碼混淆,對于前端來說可以格式化代碼后直接修改。 前端 js 基礎(chǔ)很重要,ProcessOn 沒有使用其他框架,就使用了? jquery?和?div?實(shí)現(xiàn)了流程圖而且不卡,我之前用react 也寫個(gè)類似的拓?fù)鋱D,但論流暢性和用戶體驗(yàn)遠(yuǎn)不及它。不差錢的同學(xué),還是希望大家支持正版。
最后
本篇記錄了實(shí)現(xiàn)的主要步驟,但是對于一些細(xì)節(jié),還有一些特殊代碼操作沒有記錄,希望喜歡的同學(xué)點(diǎn)個(gè)小贊,加個(gè)小星?,后續(xù)可以出更多的文章
希望這篇文章對大家有所幫助,也可以參考我往期的文章或者在評(píng)論區(qū)交流你的想法和心得,歡迎一起探索前端。
參考資料
Save All Resources :?https://chrome.google.com/webstore/detail/save-all-resources/abpdnfjocnmdomablahdcfnoggeeiedb
[2]http-server:?https://www.npmjs.com/package/http-server
[3]掘金的chrome插件:?https://chrome.google.com/webstore/detail/%E7%A8%80%E5%9C%9F%E6%8E%98%E9%87%91/lecdifefmmfjnjjinhaennhdlmcaeeeb
[4]chrome-extensions-samples:?https://github.com/GoogleChrome/chrome-extensions-samples
[5]Using eval in Chrome extensions:?https://developer.chrome.com/docs/extensions/mv3/sandboxingEval/
[6]express.js:?https://expressjs.com/
[7]postgres:?http://www.postgres.cn/docs/12/
[8]prisma:?https://prisma.io/
[9]github OAuth:?https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps
[10]Jquery:?https://jquery.com/
[11]博客:?https://maqib.cn/
[12]用 NextJS 和 TailwindCSS 重構(gòu)我的博客:?https://juejin.cn/post/6984267680324780040
[13]github:?https://github.com/maqi1520/Clone-processon
The End
點(diǎn)個(gè)?「在看」,讓更多的人也能看到這篇文章;
關(guān)注公眾號(hào)?「JS 酷」?,我們持續(xù)分享 Javascript 熱門框架和前端工程師進(jìn)階內(nèi)容;
