從PHP的Fat-Free Framework框架來看用Node.js的Express框架開發網站的心得 / Fat-Free Framework in PHP vs. Express in Node.js: Pros and Cons of Node.js
之前我跟學弟嘗試使用Node.js的Express框架來開發網站。本想著前端跟後端都可以統一使用JavaScript,但實際嘗試之後才發現Express框架問題頗多。這兩天為了把Zotero的資料庫寫成網站,我回頭使用PHP的Fat-Free Framework框架來開發,順手程度讓我感動到痛哭流涕,不禁想要寫一篇來整理一下Node.js的各種問題。這篇就閒聊一下吧。
Express每次修改程式碼後都需要重新啟動 / Express requires restart when code changed everytime
Node.js一個最出乎我意料之外的問題,就是每次修改程式碼之後都必須關閉Express、再重新啟動Express。先別提古早前開發Java時還要編譯的慘狀,我還以為自從PHP之後的網頁用程式語言都是寫了就會生效,怎想到Express的Node.js居然是要重開才能生效呢?
對沒寫程式的人來說,可能不覺得這個重新啟動的步驟有什麼特別。一般寫PHP的時候,只要改完程式、存檔、重新讀取網頁,網頁上就是修改後的內容。但是用Express來寫網頁的時候,必須是改完成、存檔、關閉Express程式、開啟Express程式(依照Node.js載入套件多寡,大概要等個5秒),重新讀取網頁、看到修改後的內容。中間多這個步驟就差了快15秒,改4次就多花1分鐘,而且那個沒有辦法作任何事情、只能等待的時間特別讓人覺得疲憊。
然而,Node.js用Express修改程式碼後需要重開的這問題不知為何很少被人提及。大家都講Node.js用JavaScript、非同步流程多棒多棒,結果這個基本又費時的缺點卻一直被人省略。
網路上針對Express需要重新啟動的問題有相當多的討論,但最後的解法看來都是:換一個框架,例如PM2。換句話說,不要用Express了吧。
Express的session的各種問題 / Session issues in Express
session是儲存使用者網頁操作狀態的一種網頁技術,很常見也很普遍。在PHP中,我們可以用$_SESSION來處理session,操作方式就跟一般的變數一樣,容易使用。在Fat-Free Framework中,我們甚至可以將session資料保存在資料庫中,方便管理。這種做法在各種PHP的框架中都很常見。
然而在Express框架中,操作session就完全不是這麼一回事。Express使用session的方法會受到Express本身的版本、Express使用的各種session套件、套件本身的版本、使用套件的宣告等多種因素的影響。如果上網去找找看,你會發現Express中使用session竟然有多種寫法。像是極客學院的cookie 和 session跟正式作業中的Express 安全最佳作法 - Express.js這兩篇做法就不相同。我看大家爭論的關鍵點都是session的安全性,但很遺憾的是,我照這兩篇的做法來操作session,全都失敗。
Cookie也有問題 / Cookie issues in Express
session有問題,那cookie總行了吧?
跟session不一樣的是,Express的cookie寫法比較統一,沒什麼爭議。我試寫了一下,cookie也的確很容易使用。
然而,因為我的程式會用到大量的跨網域應用(我好像一直都在寫這種網頁應用程式),而cookie也會用在跨網域的狀態下儲存使用者的狀態。就在這個時候,跨網域使用GET方法傳送資料的情況下,Express的cookie就會失效。
很奇怪吧?相同網域用GET沒有問題,但是跨網域用GET就會無法儲存cookie。我還真是完全沒料到會有這種問題。
最後解決方法是用POST方法跨網域儲存cookie。沒錯,奇怪的是POST就可以正常使用。為什麼呢?
優點:容易剖析HTML / Pros: Easy HTML parsing
如果要說Node.js有什麼不可或缺的特色,我可能會說:HTML剖析。
寫前端寫習慣之後,真的會覺得用jQuery來剖析HTML程式碼真的是方便到無以復加,讓人幾乎忘了正規表示法這種複雜的玩意兒。而Node.js本身也當然是可以使用jQuery,套件是jsdom,做法可以參考「jsdom + jQuery in 5 lines with node.js」這篇。在Node.js中跑原生的jQuery,比在PHP中使用什麼PHP Simple HTML DOM Parse之類的套件來剖析HTML還要好用許多。
但如果只是為了這功能而把整個系統綁死在Node.js上,未免也太不方便了。這時候不妨可以使用PhantomJS──可以用來載入網頁內容的虛擬瀏覽器,用指令列工具來截取HTML的程式碼並剖析指定的元素內容。詳細內容可以看我之前寫的「擷取AJAX動態產生的網頁內容:PhantomJS指令列工具」。
小結 / In closing
如果你在看這篇的時候,一直在質疑為什麼我沒有提到PHP的幾個問題:
- 不夠物件導向、太過程序化的寫法 (但Express其實也蠻程序化)。
- 檔案即網址造成的安全性問題,沒有Express的路由工具(routing)好用。
- 未支援新形態的資料庫,例如Redis。(不知道為什麼,很多人寫Express會搭配Redis使用)
如果你有這些問題,那可能是因為你不太知道現在PHP的發展早已經克服這些問題了。現在撰寫PHP的時候很少人是從白紙來寫網頁,而是會從框架(framework)開始撰寫。PHP知名的框架Laraval或CodeIgniter實在是過於複雜,我現在最推薦的是Fat-Free-Framework (f3),它涵蓋了幾乎我需要的各種功能,並簡潔到讓人足以快速上手。
- f3的路由跟Express的做法類似,還可以透過config.ini設定路由
- f3的路由會鼓勵開發者用物件導向開發
- PHP後來就支援Redis了,請照「PHP 使用 Redis」設定。
- f3的模板功能(template)非常好用。
不過,就算PHP多方便,我還是會希望能在後端使用JavaScript。能使用相同語言開發程式,其實真的感覺很好,就是上面寫的那些缺點討厭了些XD
PHP 在 Html Parser 有一個套件還蠻好用的,給你參考看看
回覆刪除http://symfony.com/doc/current/components/dom_crawler.html
也是用 css selector 的方式去抓 DOM
感謝推薦,下次試試
刪除Take a look at the article about Node.js pros and cons - https://www.cleveroad.com/blog/node-js-vs-ruby-on-rails--the-power-behind-technologies
回覆刪除Good luck!
Thanks!
刪除But I still prefer JavaScript (Node.js) to Ruby, however.